• CF908G New Year and Original Order 数位DP


    传送门


    看到数据范围到(10^{700})毫无疑问数位DP。那么我们最重要的问题是如何有效地维护所有数位排序之后的数的值。

    对于某一个数(x),设(f_{x,i} (i in [1,9]))表示(x)中的所有数位的值(geq i)的数位数量,比如说(f_{6345982 , 7} = 2 , f_{1982777 , 7} = 5)。那么(x = sumlimits_{i=1}^9 sumlimits_{j=0}^{f_{x,i} - 1} 10^i = frac{sumlimits_{i=1}^9 10^{f_{x,i}} - 1}{9})

    经过这一个转化,我们需要维护的就是(f_{x,i})。而(f_{x,i})在数位DP的时候很好动态地维护。

    具体来说,数位DP时记录当前填入部分的(f_{x,i}),预处理(dp_{i,j})表示对于位数恰好等于(i-1)(可以有前导(0))的所有数(p)(10^{f_{p,j}})之和,然后就可以直接算了。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int MOD = 1e9 + 7;
    string s;
    int dp[707][10] , cur[10] , L , ans , inv9;
    
    inline int poww(long long a , int b){
        int times = 1;
        while(b){
            if(b & 1) times = times * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return times;
    }
    
    void init(){
        for(int i = 1 ; i < 10 ; ++i)
            dp[0][i] = (10 - i) * 10 + i;
        for(int i = 1 ; i < L ; ++i)
            for(int j = 1 ; j < 10 ; ++j)
                dp[i][j] = dp[i - 1][j] * ((10ll - j) * 10 + j) % MOD;
    }
    
    void calc(int l){
        int sum = (MOD - 9ll * poww(10 , l + 1) % MOD) % MOD;
        for(int i = 1 ; i < 10 ; ++i)
            sum = (sum + 1ll * (l == -1 ? 1 : dp[l][i]) * poww(10 , cur[i])) % MOD;
        ans = (ans + 1ll * sum * inv9) % MOD;
    }
    
    void dfs(int l){
        if(l < 0){
            int sum = 0;
            for(int i = 1 ; i < 10 ; ++i)
                sum = (sum + poww(10 , cur[i]) - 1) % MOD;
            ans = (ans + 1ll * sum * inv9) % MOD;
            return;
        }
        for(int i = 0 ; i <= s[l] - '0' ; ++i){
            ++cur[i];
            i != s[l] - '0' ? calc(l - 1) : dfs(l - 1);
        }
    }
    
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("in","r",stdin);
        //freopen("out","w",stdout);
        #endif
        inv9 = poww(9 , MOD - 2);
        cin >> s; L = s.size(); reverse(s.begin() , s.end());
        init(); dfs(L - 1);
        cout << ans % MOD;
        return 0;
    }
    
  • 相关阅读:
    php数组转换成js可用的数组的两种方式
    常用正则表达式--------------[拿把小刀,强大自己]
    AngularJs 相应回车事件
    常见的关系型数据库和非关系型数据库及其区别
    CMDB资产采集
    GB和GiB的区别
    python枚举详解
    python保留两位小数
    详解TCP三握四挥
    npm run dev 和 npm run serve
  • 原文地址:https://www.cnblogs.com/Itst/p/10555123.html
Copyright © 2020-2023  润新知