• HackerRank


    An ACM-level problem because it involves "advanced maths". It should not be marked as "Moderate". Other than that, it is a medium level DP one.

    *Math modeling in your mind: can you see through the problem statement and figure out that it isa DP-style letter choice process? I couldn't.. This is so crucial, however.

    *DP Part: there is dependency between letters: you should pick higher chars then lower chars, and DP choice occurs during this process.

    *Maths Part: C(m + n, n) is used, but the numbers are huge, so regular combination formula is not working here. Lucas Theorem is necessary here (http://en.wikipedia.org/wiki/Lucas%27_theorem), which I will try to understand later..

    I checked Editorials, understand it and then rewrite their Jave code into my solution in C++ (it looks almost the same).

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <set>
    #include <unordered_set>
    #include <string>
    #include <climits>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #include <unordered_set>
    using namespace std;
    
    #define MAX_LEN 2501
    #define MOD 1000003
    /*
        Lucas Theorem: to compute large number of C(m, n)
     */
    class compute {
        long long Fact[MOD], rFact[MOD];
    public:
        void init(){
            Fact[0] = rFact[0] = 1;
            for (long i = 1; i < MOD; i++) {
                Fact[((int)i)] = (i * Fact[((int)(i - 1))]) % MOD;
                rFact[((int)i)] = powmod(Fact[((int)i)], MOD - 2);
            }
        }
        long long ways(long k, long n, long r){
            return lucas(n - k*(r - 1), r);
        }
        long long nCr(long n, long k) {
            if (n<0 || k<0 || k>n) return 0;
            return (((Fact[(int)n] * rFact[(int)k]) % MOD) *rFact[(int)(n - k)]) % MOD;
        }
        long long lucas(long n, long r) {
            if (n < MOD) return nCr(n, r);
            return (nCr(n / MOD, r / MOD) * nCr(n%MOD, r%MOD)) % MOD;
        }
        long long powmod(long b, long p) {
            long long ret = 1, a = b%MOD;
            while (p>0) {
                if (p % 2 == 1) ret = (ret*a) % MOD;
                a = (a*a) % MOD;
                p >>= 1;
            }
            return ret;
        }
    };
    
    compute cp;
    
    ///////////////////////
    vector<int> howMany(26);
    
    long long call(int pos, int taken, int n, int k, vector<vector<long>> &dp)
    {
        if (pos > 25) return 1;
        if (dp[pos][taken] != -1)
            return dp[pos][taken];
    
        long long ret = call(pos + 1, taken, n, k, dp);
    
        for (int i = 1; i <= howMany[pos]; i++)
        {
            if ((i + taken) > n)
                break;
            long long curr = cp.ways(k, n - taken, i) *    call(pos + 1, taken + i, n, k, dp);
            curr %= MOD;
            ret += curr;
            if (ret >= MOD) 
                ret -= MOD;
        }
        dp[pos][taken] = ret;
        return ret;
    }
    
    int main()
    {
        int n, k; cin >> n >> k;
        char buf[MAX_LEN] = {0};
        scanf("%s", buf);
        string s(buf);
        size_t len = s.length();
    
        vector<vector<long>> dp(26, vector<long>(len + 2, -1));
        for(char c : s)
            howMany[c - 'A'] ++;
    
        cp.init();
        long long ret = call(0, 0, n, k, dp);
        cout << ret << endl;
    
        return 0;
    }
    View Code
  • 相关阅读:
    sqlite 修改 id 自增值
    欧拉图与哈密顿图12:22
    nps 配置 vnc内网穿透
    0 范数、1 范数、2 范数有什么区别?
    相关测试
    golang学习笔记---channel(通道)
    golang学习笔记---pflag包
    Nginx+Keepalived配置Nginx自动启动和7*24不间断服务
    Keepalived+Nginx双机主备配置实践
    虚拟机中使用域名通过宿主window访问
  • 原文地址:https://www.cnblogs.com/tonix/p/4513975.html
Copyright © 2020-2023  润新知