题目
题意
一次操作是将这个数的每一位都加一。求将 n 进行 m 次操作后有几位。
思路
每一次操作只对当前位数有影响,所以可以一位一位考虑。
可以发现,每一位本来是一位数,如果变成两位数,那么一定是9+1=10,变成了1和0两位。
这样就可以只考虑对1和0进行操作了。
dp[i][j]表示当前位置的数字是i,进行j次操作之后获得的位数
如果i+j<10,那么操作之后还是一位。
如果i+j>=10,那么操作之后就变成两位,一位是1,一位是0。而从i到10需要10-i步,还剩j-(10-j)=i+j-10步。
所以状态转移方程为
如果i+j<10,dp[i][j]=1;
如果i+j>=10,dp[i][j]=dp[0][i+j-10]+dp[1][i+j-10];
代码如下
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=2e5+5;
const int mod=1e9+7;
typedef long long ll;
int dp[10][maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
for(int i=0;i<10;i++)
dp[i][0]=1;
for(int j=1;j<=maxn;j++)
{
for(int i=0;i<10;i++)
{
if(i+j>9)
dp[i][j]=(dp[0][i+j-10]+dp[1][i+j-10])%mod;
else
dp[i][j]=1;
}
}
int t;
cin>>t;
while(t--)
{
ll ans=0;
int n,m;
cin>>n>>m;
while(n)
{
ans+=dp[n%10][m];
ans%=mod;
n/=10;
}
cout<<ans<<endl;
}
}