【题目地址】
题目意思见原题面。
很容易看出这是个数位DP。
考虑求 l ∼ r l\sim r l∼r区间内的数,我们可以转化为求 1 ∼ l − 1 1\sim l-1 1∼l−1和 1 ∼ r 1\sim r 1∼r,然后用前缀和的思想相减即可。
此时我们只用考虑上界(下界都为1了),套用数位DP的模板,我们记录一下当前的价值和后面出现了的数的个数即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll Mod=1e9+7;
const int M=30;
struct node{
ll cnt,val;
void clear(){cnt=val=0;}
node(){}
node(ll a,ll b):cnt(a),val(b){}
}Rec[10][M];
bool vis[10][M];
int B[M],len;
node F(int num,int pos,bool ex){
if(pos==1) return node(1,num);
if(!ex&&vis[num][pos]) return Rec[num][pos];
node now,to;now.clear();
int r=ex?B[pos-1]:9;
for(int i=0;i<=r;i++){
to=F(i,pos-1,ex&&i==r);
now.val=(now.val+1ll*num*to.cnt%Mod+to.val)%Mod;
(now.cnt+=to.cnt)%=Mod;
} if(!ex){vis[num][pos]=1;Rec[num][pos]=now;}
return now;
}
ll calc(ll v){
if(v<=1) return v;
len=0;
memset(vis,0,sizeof(vis));
while(v)B[++len]=v%10,v/=10;
ll ans=0;
for(int i=0;i<=B[len];i++){
(ans+=(F(i,len,i==B[len]).val))%=Mod;
} return ans;
} ll l,r;
int main(){
int T;for(scanf("%d",&T);T--;){
scanf("%lld%lld",&l,&r);
printf("%lld\n",((calc(r)-calc(l-1))%Mod+Mod)%Mod);
} return 0;
}