题目:You are given an integer n. You have to apply mm operations to it.
In a single operation, you must replace every digit dd of the number with the decimal representation of integer d+1. For example, 1912 becomes 21023 after applying the operation once.
You have to find the length of n after applying mm operations. Since the answer can be very large, print it modulo 10^9+7.
大意:给定一个数n,每进行一次操作,这个数每一位都会+1并以十进制的形式表示,即1912进行一次操作后1->2,9->10,1->2,2->3,就变成21023,求进行m次这种操作后,n这个数的长度。
思路:对于每个位置上的数d,它对它后一位d+1贡献为1(特殊情况9分别对1、0的贡献为1)。那么,我们设dp[i][j]为进行i次操作,数字j的个数。显然,可以推出状态转移方程
当j=0时,dp[i][0]=dp[i-1][9];
当j=1时,dp[i][1]=dp[i-1][0]+dp[i-1][9];
当j!=1&&j!=0,dp[i][j]=dp[i-1][j-1];
我们注意到,如果每次都要dp递推,显然会超时(4e11)。所以我们要预处理一下,把n设为10,m=2e5,这样问题就转化为,这个数到10需要k次。最后可得出答案。
代码:
#include<bits/stdc++.h>
using namespace std;
long long mod=1e9+7;
long long dp[200005][15],a[15],sum[200005];
int main()
{
int t;
scanf("%d",&t);
dp[0][0]=dp[0][1]=1;
sum[0]=2;
for(int i=1;i<=200000;i++)
{
for(int j=0;j<=9;j++)
{
if(j==0) dp[i][j]=(dp[i-1][9])%mod;
else if(j==1) dp[i][j]=(dp[i-1][0]+dp[i-1][9])%mod;
else dp[i][j]=(dp[i-1][j-1])%mod;
sum[i]=(sum[i]+dp[i][j])%mod;
}
}
while(t--)
{
long long n;
int m;
memset(a,0,sizeof(a));
scanf("%lld %d",&n,&m);
while(n){
a[n%10]++;
n/=10;
}
long long ans=0;
for(int i=0;i<=9;i++)
{
if(a[i]){
if(m-(10-i)>=0) ans=(ans+a[i]*sum[m-(10-i)])%mod;
else ans=(ans+a[i])%mod;
}
}
printf("%lld\n",ans);
}
}