首页 > 代码库 > poj 1715 Hexadecimal Numbers 排列组合

poj 1715 Hexadecimal Numbers 排列组合

 1 /**
 2 大意: 给定16进制数的16个字母,,求第k大的数,,要求数的长度最大为8.,并且每个数互不相同。
 3 思路: 从高到低挨个枚举,每一位能组成的排列数 ,拿最高位来说,能做成的排列数为15*A(15,len-i)
 4           第二位 A(14,len-2)。。这样就可以找到k大的数的长度
 5 接下来 。找第k大的数。同上理 ,挨个枚举每一位即可。。若加上该位的排列数大于k,则该位就是这个数,继续枚举下一位
 6 **/
 7 
 8 /**  大神思路
 9 首先确定数字串的长度Len:从大到小枚举Len,每个Len下有15*P(15, Len-1)个数字串。每次用这个个数扣除输入的序数Count,直到序数Count将扣为负数时停止,就确定了长度Len。
10  
11 然后从高位到低位,从大到小确定每位数字:设当前确定的数字为第i位,则第i位的任何一个取值,都有P(16 - (Len - i + 1), i - 1)个数字串将已确定的第1到i位作为前缀。每次用这个个数扣除输入的序数Count,直到序数Count将扣为负数时停止,就确定了当前位的数字。
12  
13 注意不能有前导0。
14 **/
15 #include <iostream>
16 
17 using namespace std;
18 char num[16]={0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F};
19 int ans[10];
20 
21 int Axy(int x,int y){
22     int res =1;
23     if(y==0)
24         return 1;
25     while(y--){
26         res *= x;
27         x--;
28     }
29     return res;
30 }
31 
32 void solve(int count){
33     bool vis[16]={0},head = false;
34     int uselen = 0,countv;
35     for(int i=1;i<=8;i++){
36         int cnt = 15;
37         while(cnt){
38             if(!vis[cnt]){
39                 if((countv = Axy(16-1-uselen,8-i))<count){
40                     count -= countv;
41                 }else{
42                     vis[cnt] = true;
43                     break;
44                 }
45             }
46             cnt--;
47         }
48         ans[i] = num[cnt];
49         if(head||ans[i]!=0) uselen++;
50         if(ans[i]!=0) head = true;
51     }
52 }
53 
54 int main()
55 {
56     int cnt;
57     while(cin>>cnt){
58         bool head = false;
59         solve(cnt);
60         for(int i=1;i<=8;i++){     
61             if(head||ans[i]!=0){     //去除前导0
62                 cout<<(char)ans[i];
63                 head = true;
64             }
65         }
66         if(!head)     // 若全为0 ,则输出0
67             cout<<0;
68         cout<<endl;
69     }
70     return 0;
71 }