题目链接
题意:给定初始整数n和操作数m,每一次操作都可以把n里的每个数字加1,问m此操作后n的长度是多少,比如n=1912,操作一次后就是21023,长度为5.
思路:首先肯定不能暴力,我们可以发现每次使得长度增加的无非就是9->10这一部,但是如果直接定义dp【i】为操作次数i的长度好象不好转移。所以我们可以定义dp[i][j]代表初始数字为10时第i此操作,数位上有数字j的个数为dp[i][j],那么答案就是dp【i】【j】(j从0到9)的累加和也就是代码里的sum【i】。比如n为5,操作数100,5变为10的话就是5步,剩下就是就是再加上sum【100-5】。每一位数字都是独立不影响,所以遍历累加就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int mod=1e9+7;
ll sum[maxn],dp[maxn][10];//dp[i][j]代表第i此操作,数位上有数字j的个数为dp[i][j]
vector<int>v;
void init()
{
dp[0][1]=1;dp[0][0]=1;sum[0]=2;
for(int i=1;i<maxn;++i)
for(int j=0;j<=9;++j)
{
if(j) dp[i][j]=dp[i-1][j-1];
if(j==0||j==1) dp[i][j]=(dp[i][j]+dp[i-1][9])%mod;
sum[i]=(sum[i]+dp[i][j])%mod;
}
}
int main()
{
int T,n,m;
init();
scanf("%d",&T);
while(T--)
{
v.clear();
scanf("%d%d",&n,&m);
ll ans=0;
while(n>0)
{
v.push_back(n%10);
n/=10;
}
for(int i:v)
{
int x=10-i;
if(m<x) ans=(ans+1)%mod;
else ans=(ans+sum[m-x])%mod;
}
printf("%lld\n",ans);
}
}