|
| 1 | +# 题目链接 |
| 2 | + |
| 3 | +[E. Segment Sum](http://codeforces.com/contest/1073/problem/E) |
| 4 | + |
| 5 | +# 分析 |
| 6 | + |
| 7 | +可以说很经典了,数位 dp,关于数位dp我也才学 |
| 8 | + |
| 9 | +[数位dp](https://codeforces.com/blog/entry/53960) |
| 10 | + |
| 11 | +这个题目与 仅统计个数有点不同的地方在于,它要求值的和,而对于整数来说每个位是可以独立相加的,可是如果仅仅用一个状态 dp[st][pos][0/1] 表示吃状态下的最终结果的话,可能不行,因为比如 |
| 12 | + |
| 13 | +1232** |
| 14 | +1233** 这两种情况其实是在一个 dp 状态下的 st = 111,pos = 3 |
| 15 | +所以会遗漏一些位的计算,所以我们采用 计算每个位贡献和(单独的位可相加)的方式将后面的值加起来 |
| 16 | + |
| 17 | +所以计算两个量一个是个数,一个是当前值 |
| 18 | + |
| 19 | +# code |
| 20 | + |
| 21 | +```cpp |
| 22 | +#include<bits/stdc++.h> |
| 23 | +using namespace std; |
| 24 | + |
| 25 | +#define MAX_VAL 110 |
| 26 | +#define MAX_ARRAY_SIZE 20 |
| 27 | +#define ms(x,v) memset((x),(v),sizeof(x)) |
| 28 | +#define pb push_back |
| 29 | +#define fi first |
| 30 | +#define se second |
| 31 | +#define mp make_pair |
| 32 | +#define INF 0x3f3f3f3f |
| 33 | +#define MOD 998244353 |
| 34 | +#define CTZ(x) __builtin_ctz(x) //the number of zeros at the end of number |
| 35 | +#define CLZ(x) __builtin_clz(x) //the number of zeros at the begin of number |
| 36 | +#define POPCNT(x) __builtin_popcount(x) //the number of ones in the number |
| 37 | +#define PARITY(x) __builtin_parity(x) //the parity(odd or even) of the number |
| 38 | + |
| 39 | +typedef long long LL; |
| 40 | +typedef pair<LL,LL> Pair; |
| 41 | +int k; |
| 42 | +LL a,b; |
| 43 | +int num[MAX_ARRAY_SIZE],cnt; |
| 44 | +LL dp[1<<10][MAX_ARRAY_SIZE][2]; |
| 45 | +LL ans[1<<10][MAX_ARRAY_SIZE][2]; |
| 46 | +LL pw[MAX_ARRAY_SIZE]; |
| 47 | + |
| 48 | +pair<LL,LL> calc(const int st,const int pos,const int f){ |
| 49 | + if(POPCNT(st)>k)return mp(0,0); |
| 50 | + if(pos == cnt){ |
| 51 | + return mp(0,1); |
| 52 | + } |
| 53 | + pair<LL,LL> ret = mp(ans[st][pos][f],dp[st][pos][f]); |
| 54 | + if(ret.se !=-1)return ret; |
| 55 | + ret = mp(0,0); |
| 56 | + int lmt = f? 9: num[pos]; |
| 57 | + for(int i=0 ; i<=lmt ; ++i){ |
| 58 | + Pair tmp=mp(0,0); |
| 59 | + if(st ==0){ |
| 60 | + tmp = calc(i?1<<i : 0,pos+1,f||i<lmt); |
| 61 | + } |
| 62 | + else{ |
| 63 | + tmp = calc(st|1<<i,pos+1,f||i<lmt); |
| 64 | + } |
| 65 | + ret.fi += i*pw[cnt-pos-1]%MOD * tmp.se % MOD+ tmp.fi; |
| 66 | + ret.se += tmp.se; |
| 67 | + } |
| 68 | + return mp(ans[st][pos][f] = ret.fi % MOD, dp[st][pos][f] = ret.se %MOD); |
| 69 | +} |
| 70 | + |
| 71 | +LL solve(const LL n){ |
| 72 | + cnt =0; |
| 73 | + ms(dp,-1); |
| 74 | + ms(ans,-1); |
| 75 | + LL debug_n = n; |
| 76 | + while (debug_n) { |
| 77 | + num[cnt++] = debug_n % 10; |
| 78 | + debug_n/=10; |
| 79 | + } |
| 80 | + reverse(num,num+cnt); |
| 81 | + Pair ret = calc(0,0,0); |
| 82 | + return ret.fi; |
| 83 | +} |
| 84 | + |
| 85 | + |
| 86 | +int main (int argc, char const *argv[]) { |
| 87 | + ios_base::sync_with_stdio(0); |
| 88 | + cin.tie(0); |
| 89 | + pw[0] =1; |
| 90 | + for(int i=1 ; i<MAX_ARRAY_SIZE ; ++i)pw[i] = pw[i-1]*10 %MOD; |
| 91 | + |
| 92 | + cin >> a >> b >> k; |
| 93 | + std::cout << (solve(b) - solve(a -1) + MOD) % MOD << '\n'; |
| 94 | + return 0; |
| 95 | +} |
| 96 | + |
| 97 | +``` |
0 commit comments