数位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);
}
}


京公网安备 11010502036488号