标签:
思路:从高位往地位考虑,对于当前位p,从大到小考虑当前位的取值v,如果v在之前被使用过则跳过v继续考虑v-1;否则考虑当前位取v时后面的位能取到的数的总个数Acnt,
如果Acnt >= cnt,则表明当前位取v可以涵盖cnt,然后跳出;否则cnt -= Acnt.
#include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> #include <algorithm> #include <set> #include <queue> #include <stack> #include <map> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const double pi= acos(-1.0); int vis[16]; char num[16]= {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char ans[16]; int A(int n,int m)//计算排列数A(n,m); { int res=1; if(m==0) return 1; while(m--) { res*=n; n--; } return res; } void Solve(int cnt) { memset(vis,0,sizeof(vis)); int i; int Acnt; int Ncnt; int Ulen=0; int flag=0; for(i=1; i<=8; i++) {//从高位往低位考虑 Ncnt=15;//对应16进制字母的位置 while(Ncnt) {//一次遍历当前位所有可能的取值 if(!vis[Ncnt]) { Acnt=A(15-Ulen,8-i); if(Acnt<cnt) cnt-=Acnt; else { vis[Ncnt]=1; break; } } Ncnt--; } ans[i]=num[Ncnt]; //要注意统计当前有效位的长度 if(ans[i]!='0') flag=1; if(flag||ans[i]!='0') Ulen++; } } int main() { int n,i; int flag; while(~scanf("%d",&n)){ Solve(n); flag=0; for(i=1;i<=8;i++){ if(flag||ans[i]!='0'){ printf("%c",ans[i]); flag=1; } } if(!flag) printf("0"); printf("\n"); } return 0; }
POJ 1715- Hexadecimal Numbers(组合数学)
标签:
原文地址:http://blog.csdn.net/u013486414/article/details/45008659