Codeforces1073E Segment Sum 数位DP

Posted menhera

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1073E Segment Sum 数位DP相关的知识,希望对你有一定的参考价值。

题目分析:

裸的数位DP,注意细节。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int mod = 998244353;
 5 int k;
 6 
 7 int dp[25][1024],sz[25][1024],cnt[25][1024];
 8 int pw10[25],hp[25],num;
 9 
10 int dfs(int now,int lst){
11     if(now == 0) return 0;
12     int ans = 0;
13     for(int i=0;i<hp[now];i++){
14     for(int j=0;j<(1<<10);j++){
15         int pp = (lst==0&&i==0?0:(1<<i));
16         int z = __builtin_popcount(j|pp|lst);
17         if(z > k) continue;
18         ans += 1ll*sz[now-1][j]*pw10[now-1]%mod*i%mod; ans %= mod;
19         ans += dp[now-1][j]; ans %= mod;
20     }
21     }
22     if(now == num){
23     for(int i=1;i<num-1;i++){
24         for(int j=0;j<(1<<10);j++){
25         int z = __builtin_popcount(j);
26         if(z > k) continue;
27         z = __builtin_popcount(j|1);
28         if(z <= k) continue;
29         ans += dp[i][j]; ans %= mod;
30         }
31     }
32     }
33     for(int i=0;i<(1<<10);i++){
34     int z = __builtin_popcount(i|(1<<hp[now])|lst);
35     if(z > k) continue;
36     ans += 1ll*cnt[now-1][i]*pw10[now-1]%mod*hp[now]%mod;
37     ans %= mod;
38     }
39     ans += dfs(now-1,lst|(1<<hp[now]));
40     ans %= mod;
41     return ans;
42 }
43 
44 int solve(long long now){
45     num = 0;
46     memset(cnt,0,sizeof(cnt));cnt[0][0] = 1;
47     while(now){hp[++num] = now%10;now /= 10;}
48     for(int i=1;i<=num;i++){
49     for(int j=0;j<hp[i];j++){
50         for(int k=0;k<(1<<10);k++){
51         cnt[i][k|(1<<j)] += sz[i-1][k];
52         cnt[i][k|(1<<j)] %= mod;
53         }
54     }
55     for(int k=0;k<(1<<10);k++){
56         cnt[i][k|(1<<hp[i])] += cnt[i-1][k];
57         cnt[i][k|(1<<hp[i])] %= mod;
58     }
59     }
60     return dfs(num,0);
61 }
62 
63 int main(){
64     long long l,r;
65     cin >>l >> r >> k;
66     sz[0][0] = 1;pw10[0] = 1;
67     for(int i=1;i<=20;i++) pw10[i] = 1ll*pw10[i-1]*10%mod;
68     for(int i=1;i<=20;i++){
69     for(int f = 1;f<=9;f++){
70         for(int j=0;j<(1<<10);j++){
71         sz[i][j|(1<<f)] += sz[i-1][j]; sz[i][j|(1<<f)]%=mod;
72         dp[i][j|(1<<f)] += dp[i-1][j]; dp[i][j|(1<<f)] %= mod;
73         dp[i][j|(1<<f)] += 1ll*sz[i-1][j]*pw10[i-1]%mod*f%mod;
74         dp[i][j|(1<<f)] %= mod;
75         for(int k=0;k<i-1;k++){
76             sz[i][j|(1<<f)|1] += sz[k][j]; sz[i][j|(1<<f)|1]%=mod;
77             dp[i][j|(1<<f)|1] += dp[k][j]; dp[i][j|(1<<f)|1]%=mod;
78             dp[i][j|(1<<f)|1] += 1ll*sz[k][j]*pw10[i-1]*f%mod;
79             dp[i][j|(1<<f)|1] %= mod;
80         }
81         }
82     }
83     }
84     for(int i=1;i<=20;i++){
85     for(int j=0;j<(1<<10);j++){
86         sz[i][j|1] += sz[i-1][j];
87         dp[i][j|1] += dp[i-1][j];
88         sz[i][j|1] %= mod; dp[i][j|1] %= mod;
89     }
90     }
91     long long ans = solve(r)-solve(l-1);
92     ans+=mod; ans %= mod;
93     cout<<ans<<endl;
94     return 0;
95 }

 

以上是关于Codeforces1073E Segment Sum 数位DP的主要内容,如果未能解决你的问题,请参考以下文章

CF1073E Segment Sum 解题报告

codeforces 1073E

Educational Codeforces Round 48 (Rated for Div. 2) B Segment Occurrences

Educational Codeforces Round 48 (Rated for Div. 2) B. Segment Occurrences(数组前缀和防TLE)

codeforces 620C

CodeForces 616DLongest k-Good Segment