POJ-1715 Hexadecimal Numbers 组合数学

这题写的真心有点纠结。首先确定需要多少位来容纳这个数,然后找到第一个要更新的位置,再逐位更新。

代码如下:

#include <cstdlib>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

using namespace std;



typedef long long int Int64;



bool hash[20];



int digit[10], Most;



Int64 s[10], f[20], N;



void pre()

{

    f[0] = s[0] = 1;

    for (int i = 1; i <= 16; ++i) {

        f[i] = f[i-1] * i;

    }

    for (int i = 1; i <= 8; ++i) {

        s[i] = f[16-Most+i] / f[16-Most];

    }

    s[Most] -= s[Most-1];

}



void update(int pos)

{

    for (int i = 15; i >= 0; --i) {

        if (!hash[i]) {

            digit[pos] = i;    

            hash[digit[pos]] = true;

            return;

        }

    }

}



void dfs(int pos, Int64 k, int start)  

// 需要开始调整的位置以及需要调整的指数

{

    int deep = (int)floor(1.0 * k / s[pos-1]), cnt = 0, left;

    if (deep) {

        hash[digit[pos]] = false;

        for (int i = start; i >= 0; --i) {

            if (!hash[i]) {

                ++cnt;

            }

            if (cnt == deep) {

                digit[pos] = i;

                hash[digit[pos]] = true;

                break;

            }

        } // 这一位我们就确定了下来

    }

    left = k-deep*s[pos-1];

    if (pos-1 > 0) {

        update(pos-1);

        dfs(pos-1, left, digit[pos-1]-1);

    }

}



void init()

{

    pre();

    memset(digit, 0, sizeof (digit));

    memset(hash, 0, sizeof (hash));

    for (int i = 16 - Most, j = 1; i <= 15; ++i, ++j) {

        hash[i] = true;  // 声明出这些数是已占用的 

        digit[j] = i;

    }

}



int main()

{

    while (scanf("%I64d", &N) == 1) {

        pre();

        N -= 1;

        for (int i = 8; i >= 1; --i) {

            N -= 15 * f[15]/f[15-i+1];

            if (N < 0) {

                N += 15 * f[15]/f[15-i+1];

                Most = i;

                break;

            }

        }

        init();

        for (int i = 1; i <= Most; ++i) {

            hash[digit[i]] = false;

            if (N - s[i] < 0) {

                dfs(i, N, digit[i]-1);

                break;

            }

        }

        for (int i = Most; i >= 1; --i) {

            if (digit[i] > 9) {

                printf("%c", digit[i]-10+'A');

            }

            else {

                printf("%d", digit[i]);    

            }

        }

        puts("");

    }

    return 0;    

}

你可能感兴趣的:(number)