zoukankan      html  css  js  c++  java
  • POJ1715 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;    
    }
  • 相关阅读:
    Gym 101466(完整)
    HDU 3639 Hawk-and-Chicken (强连通缩点+DFS)
    hdu3394--Railway(点的双连通分量)
    hdu2732 Leapin' Lizards 最大流+拆点
    hdu2609 How many 字典树+最小表示法
    hdu2594 Simpsons’ Hidden Talents LCS--扩展KMP
    hdu2509 Be the Winner 博弈
    hdu2461 Rectangles 线段树--扫描线
    hdu2389 Rain on your Parade 二分图匹配--HK算法
    hdu2328 Corporate Identity 扩展KMP
  • 原文地址:https://www.cnblogs.com/Lyush/p/2629131.html
Copyright © 2011-2022 走看看