您的位置:首页 > 其它

POJ-1715 Hexadecimal Numbers 组合数学

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

代码如下:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: