zoukankan      html  css  js  c++  java
  • Luogu4345 SHOI2015 超能粒子炮·改 Lucas、数位DP

    传送门


    模数小,还是个质数,Lucas没得跑

    考虑Lucas的实质。设(a = sumlimits_{i=0}^5 a_i 2333^i)(b = sumlimits_{i=0}^5 b_i2333^i),那么(C_a^b mod2333 = prodlimits_{i=0}^5 C_{a_i}^{b_i} mod 2333)

    可以认为Lucas就是将(a,b)两个数化成(2333)进制数之后每一位组合运算的乘积。似乎与数位相关,使用类似于数位DP的思考方式,从高到低填数。

    因为现在需要求的是(sumlimits_{i=0}^k C_n^i),假设(k)(2333)进制下表示为(overline {k_5k_4k_3k_2k_1k_0})(n)(2333)进制下表示为(overline{n_5n_4n_3n_2n_1n_0}),那么对于第(5)(< k_5)的数,后面的四位一定会取到(0)(2332)的所有值。我们处理出(prod limits _{i=0}^4 sumlimits_{j=0}^{2332} C_{n_i}^j),根据二项式定理这其实就是(2^{n_0+n_1+n_2+n_3+n_4}),那么(2333)进制下第(5)(<k_5)的所有数的贡献就是(2^{n_0+n_1+n_2+n_3+n_4}sumlimits_{i=0}^{k_5-1}C_{n_5}^i)

    最后考虑第(5)位等于(k_5)的情况,在这种情况下接着考虑第(4)位,方式跟上面一致,不断做下去直到所有位都被考虑完。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<algorithm>
    #include<cstring>
    #include<iomanip>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #include<stack>
    #include<vector>
    #include<cmath>
    #define ll long long
    //This code is written by Itst
    using namespace std;
    
    inline ll read(){
        ll a = 0;
        char c = getchar();
        bool f = 0;
        while(!isdigit(c) && c != EOF){
            if(c == '-')
                f = 1;
            c = getchar();
        }
        if(c == EOF)
            exit(0);
        while(isdigit(c)){
            a = a * 10 + c - 48;
            c = getchar();
        }
        return f ? -a : a;
    }
    
    const int MOD = 2333;
    int C[MOD][MOD] , inv[MOD] , sum[6] , mod[6];
    ll powM[6];
    
    inline int poww(int a , int b){
        int times = 1;
        while(b){
            if(b & 1)
                times = times * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return times;
    }
    
    int calc(ll cur , int now){
        if(now < 0)
            return 1;
        if(cur / powM[now])
            return (C[mod[now]][cur / powM[now] - 1] * sum[now] + (C[mod[now]][cur / powM[now]] - C[mod[now]][cur / powM[now] - 1] + MOD) * calc(cur % powM[now] , now - 1)) % MOD;
        return calc(cur , now - 1);
    }
    
    void init(){
        powM[0] = sum[0] = 1;
        for(int i = 1 ; i <= 5 ; ++i)
            powM[i] = powM[i - 1] * MOD;
        C[0][0] = 1;
        for(int i = 1 ; i < MOD ; ++i){
            C[i][0] = 1;
            for(int j = 1 ; j < MOD ; ++j)
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
        }
        for(int i = 0 ; i < MOD ; ++i)
            for(int j = 1 ; j < MOD ; ++j)
                C[i][j] = (C[i][j] + C[i][j - 1]) % MOD;
    }
    
    signed main(){
    #ifndef ONLINE_JUDGE
        freopen("in","r",stdin);
        freopen("out","w",stdout);
    #endif
        init();
        for(int T = read() ; T ; --T){
            ll N = read() , K = read();
            for(int i = 1 ; i <= 5 ; ++i){
                mod[i - 1] = N / powM[i - 1] % 2333;
                sum[i] = poww(2 , mod[i - 1]) * sum[i - 1] % MOD;
            }
            mod[5] = N / powM[5];
            cout << calc(K , 5) << '
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    代码:城市名称的联想下拉框。可按拼音搜索、按汉字搜索,是一种很简单的实现方式
    代码:拖拽
    插件:zTree
    代码:遍历
    学习笔记:Stage.js(又叫Cut.js)——2D canvas 开发库,游戏方面的
    前端模块化、构建工具
    二级联动下拉菜单
    thinkphp的目录结构设计经验总结
    tp 路径表示
    liunx 根目录介绍
  • 原文地址:https://www.cnblogs.com/Itst/p/10345189.html
Copyright © 2011-2022 走看看