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;    
}
posted @ 2012-08-08 22:23  沐阳  阅读(460)  评论(0编辑  收藏  举报