题目链接:https://www.luogu.com.cn/problem/P4999
和前面几道题的思路差不多。不难发现一个数每个数位上的和最大不过18*9,所以我们可以枚举数位和为1,和为2,和为3...然后看每一个有几个数,那么累计一下(和*个数)即为答案。
注意在mod的时候一些细节(比如减法中的mod),同时要多mod几下。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 typedef long long ll; 8 const int mod=1e9+7; 9 ll dp[20][200][200],ans[200]; 10 int a[20]; 11 ll DFS(int pos,int limit,int now,int cnt){ 12 if(pos==0) return now==cnt; 13 if(!limit&&dp[pos][now][cnt]!=-1) return dp[pos][now][cnt]; 14 int up=limit?a[pos]:9; 15 ll sum=0; 16 for(int i=0;i<=up;i++) sum+=DFS(pos-1,limit&&i==a[pos],now+i,cnt); 17 if(!limit) dp[pos][now][cnt]=sum; 18 return sum; 19 } 20 ll solve(ll x){ 21 int len=0; 22 ll sum=0; 23 while(x){ 24 a[++len]=x%10; 25 x/=10; 26 } 27 for(int i=1;i<=9*len;i++){ 28 ans[i]=DFS(len,1,0,i); 29 sum=(sum+i*(ans[i]%mod))%mod; 30 } 31 return sum; 32 } 33 int main(){ 34 int t; 35 ll n,m; 36 memset(dp,-1,sizeof(dp)); 37 scanf("%d",&t); 38 while(t--){ 39 scanf("%lld%lld",&n,&m); 40 printf("%lld ",(solve(m)-solve(n-1)+mod)%mod);// 41 } 42 return 0; 43 }