CF 1073E Segment Sum
题意:求[L,R]中,不同数位不超过k个数的和。
题解:很简单的数位dp,dp [i] [j] 表示第i位前面的数字中,前导0之外不同数位的状态为j的数字个数和它们的和(用个pair来存)。然后正常数位dp就行了,特殊处理一下前导0(加状态比较好处理)。
#include <bits/stdc++.h>
#define fi first
#define se second
#define MP make_pair
using namespace std;
typedef long long LL;
const int N = 25;
const int M = 1<<10;
const int MOD = 998244353;
typedef pair<int,int> PII;
PII f[N][M+5][2][2];
LL l, r, k;
int st[N], tol;
LL num[M+5], v[N];
PII dfs(int dep, int state, int flag, int head){
if(dep==0){
if(num[state]<=k)return MP(0,1);
else return MP(0,0);
}
if(~f[dep][state][flag][head].fi)return f[dep][state][flag][head];
PII& res=f[dep][state][flag][head];
res.fi=res.se=0;
int up=flag?st[dep]:9;
for(int i=0;i<=up;++i){
int t;
if(head&&i==0){
t=state;
}else{
t=state|(1<<i);
}
PII p=dfs(dep-1,t,flag&&i==up,head&&i==0);
res.se+=p.se;
res.se%=MOD;
res.fi+=(1ll*v[dep]*i%MOD*p.se%MOD+p.fi)%MOD;
res.fi%=MOD;
}
return res;
}
LL cal(LL x){
memset(f,-1,sizeof f);
tol=0;
while(x>0){
st[++tol]=x%10;
x/=10;
}
return dfs(tol, 0, 1, 1).fi;
}
int main(){
cin>>l>>r>>k;
num[1]=1;
for(int i=2;i<=M;++i)num[i]=num[i>>1]+(i&1);
v[1]=1;
for(int i=2;i<=19;++i)v[i]=v[i-1]*10ll%MOD;
int ra=cal(r), la=cal(l-1);
int ans=(ra-la)%MOD;
if(ans<0)ans+=MOD;
cout<<ans;
return 0;
}