题意:
给定一个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; }