1. 程式人生 > >CF 1073E. Segment Sum(digit DP)

CF 1073E. Segment Sum(digit DP)

題目連結

E. Segment Sum

分析

可以說很經典了,數位 dp,關於數位dp我也才學

數位dp

這個題目與 僅統計個數有點不同的地方在於,它要求值的和,而對於整數來說每個位是可以獨立相加的,可是如果僅僅用一個狀態 dp[st][pos][0/1] 表示吃狀態下的最終結果的話,可能不行,因為比如

1232**
1233** 這兩種情況其實是在一個 dp 狀態下的 st = 111,pos = 3
所以會遺漏一些位的計算,所以我們採用 計算每個位貢獻和(單獨的位可相加)的方式將後面的值加起來

所以計算兩個量一個是個數,一個是當前值

code

#include
<bits/stdc++.h>
using namespace std; #define MAX_VAL 110 #define MAX_ARRAY_SIZE 20 #define ms(x,v) memset((x),(v),sizeof(x)) #define pb push_back #define fi first #define se second #define mp make_pair #define INF 0x3f3f3f3f
#define MOD 998244353 #define CTZ(x) __builtin_ctz(x) //the number of zeros at the end of number #define CLZ(x) __builtin_clz(x) //the number of zeros at the begin of number #define POPCNT(x) __builtin_popcount(x) //the number of ones in the number #define
PARITY(x) __builtin_parity(x)
//the parity(odd or even) of the number typedef long long LL; typedef pair<LL,LL> Pair; int k; LL a,b; int num[MAX_ARRAY_SIZE],cnt; LL dp[1<<10][MAX_ARRAY_SIZE][2]; LL ans[1<<10][MAX_ARRAY_SIZE][2]; LL pw[MAX_ARRAY_SIZE]; pair<LL,LL> calc(const int st,const int pos,const int f){ if(POPCNT(st)>k)return mp(0,0); if(pos == cnt){ return mp(0,1); } pair<LL,LL> ret = mp(ans[st][pos][f],dp[st][pos][f]); if(ret.se !=-1)return ret; ret = mp(0,0); int lmt = f? 9: num[pos]; for(int i=0 ; i<=lmt ; ++i){ Pair tmp=mp(0,0); if(st ==0){ tmp = calc(i?1<<i : 0,pos+1,f||i<lmt); } else{ tmp = calc(st|1<<i,pos+1,f||i<lmt); } ret.fi += i*pw[cnt-pos-1]%MOD * tmp.se % MOD+ tmp.fi; ret.se += tmp.se; } return mp(ans[st][pos][f] = ret.fi % MOD, dp[st][pos][f] = ret.se %MOD); } LL solve(const LL n){ cnt =0; ms(dp,-1); ms(ans,-1); LL debug_n = n; while (debug_n) { num[cnt++] = debug_n % 10; debug_n/=10; } reverse(num,num+cnt); Pair ret = calc(0,0,0); return ret.fi; } int main (int argc, char const *argv[]) { ios_base::sync_with_stdio(0); cin.tie(0); pw[0] =1; for(int i=1 ; i<MAX_ARRAY_SIZE ; ++i)pw[i] = pw[i-1]*10 %MOD; cin >> a >> b >> k; std::cout << (solve(b) - solve(a -1) + MOD) % MOD << '\n'; return 0; }