POJ - 1715 Hexadecimal Numbers——组合数
原创
©著作权归作者所有:来自51CTO博客作者软糖酱八号机的原创作品,请联系作者获取转载授权,否则将追究法律责任
题意:
给定一个k,求第k大的每位都不相同的16进制数
思路:
题目中要求第k大,可以转化一下求第(sum-k+1)小,这样好想一些。这就要求我们首先求出情况总数sum,这个可以用全排列公式来求,不过一定要注意前导0。
之后就是普通的累加求和过程
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const char output[16]= {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
long long A[100][100], bit[100], sum;
bool vis[100];
void init() {
A[0][0] = 1;
for (int i = 1; i <= 16; i++) {
A[i][0] = 1;
for (int j = 1; j <= i; j++) {
A[i][j] = A[i][j-1] * (i - j + 1);
}
}
for (int i = 1; i <= 8; i++) {
bit[i] = 15 * A[15][i-1];
sum += bit[i];
}
}
void solve(long long x) {
memset(vis, false, sizeof(vis));
x = sum - x + 1;
if (x <= 0) { printf("0\n"); return; }
int len = 0;
for (int i = 1; i <= 8; i++) {
if (bit[i] >= x) { len = i; break; }
else x -= bit[i];
}
for (int i = 1; i <= len; i++) {
for (int j = (i == 1 ? 2 : 1); j <= 16; j++) {
if (vis[j]) continue;
if (A[16-i][len-i] >= x) { vis[j] = true; printf("%c", output[j-1]); break; }
else x -= A[16-i][len-i];
}
}
printf("\n");
}
int main() {
init();
long long n;
while (~scanf("%lld", &n)) solve(n);
return 0;
}