POJ - 1715 Hexadecimal Numbers——组合数

题意:

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

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/80247977
今日推荐