POJ 1715- Hexadecimal Numbers(组合数学)

来源:互联网 发布:程序员转行做销售 编辑:程序博客网 时间:2024/05/16 12:08

 Hexadecimal Numbers
Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u
Submit Status Practice POJ 1715
Appoint description: 

Description

The base of the hexadecimal system is 16. In order to write down numbers in this system one uses 16 digits 0,1,...,9,A,B,C,D,E,F. The capital letters A,..,F stands for 10,..,15, respectively. For instance the value of the hexadecimal number CF2 is 12 * 162 + 15 * 16 + 2 = 3314 in the decimal system. Let X be the set of all positive integers whose hexadecimal representations have at most 8 digits and do not contain repetitions of any digit. The most significant digit in such a representation is not zero. The largest element in X is the number with the hexadecimal representation FEDCBA98, the second largest is the number FEDCBA97, the third is FEDCBA96 and so forth. 
Write a program that: finds the n-th largest element of X;

Input

The first line of the file standard input contains integer n in the decimal representation. n does not exceed the number of elements of X.

Output

Your program should output the n-th largest element in X in the hexadecimal representation.

Sample Input

11

Sample Output

FEDCBA87

题意:给定16进制数的16个字母,,求第k大的数,,要求数的长度最大为8.,并且每个数互不相同。

思路:从高位往地位考虑,对于当前位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;}

 

0 0