数位dp,注意当出现次数大于限制次数的时候直接返回0,pos==0还不大于就返回1
f[pos][num][cnt] 表示第pos位,末尾数字为num,连续次数为cnt
如果下一位还是num,那么转移到dp(pos-1,num,cnt+1)
否则转移到dp(pos-1,i,1)
也就是说转移到新的数字 这个数字连续出现了一次。
最后注意答案算出来要加上mod再取余一次
#include <bits/stdc++.h> using namespace std; const int mod=20020219; #define int long long int book[20]; int f[20][20][20]; int a[11]; int dp(int pos,int num,int cnt,int flag) { if(cnt>book[num]) return 0; if(pos==0) return 1; if(flag&&f[pos][num][cnt]!=-1) return f[pos][num][cnt]; int x=flag?9:a[pos]; int ans=0; for(int i=0;i<=x;i++) { if(i==num) ans=(ans+dp(pos-1,i,cnt+1,flag||i<x))%mod; else ans=(ans+dp(pos-1,i,1,flag||i<x))%mod; } if(flag) f[pos][num][cnt]=ans; return ans; } int cul(int x) { int pos=0; while(x) { a[++pos]=x%10; x/=10; } return dp(pos,0,0,false); } signed main() { int t; scanf("%d",&t); while(t--) { memset(f,-1,sizeof(f)); memset(a,0,sizeof(a)); memset(book,0x3f3f3f3f,sizeof(book)); int l,r,n; scanf("%lld%lld%lld",&l,&r,&n); while(n--) { int num,cnt; scanf("%lld%lld",&num,&cnt); book[num]=min(book[num],cnt); } printf("%lld\n",(cul(r)-cul(l-1)+mod)%mod); } }