My solution

· · 题解

这道题算是比较套路的一道题目吧,下面是我的方法:

$2.$ 由于 $f(n)$ 的值下降迅速,而 $n$ 的值很大,所以考虑先进行一次操作,于是易知新的 $n'\le9000$,可以进行计算。 $3.$ 经过上面两步的转化,对于任意一个满足 $g(t,\min(4,k)-1)=m$ 的 $t$,答案都可以加上 $\le n$ 并且数位和为 $t$ 的数的个数。 $4.$ 由于 $3$,即把统计答案的过程分为两部分: $1)$ 统计数位和为 $t(t\le9000)$ 的数的个数(非常简单的数位 $dp$)。 $2)$ 按照 $3$ 的思路统计答案。 $5.$ 时间复杂度正确,可以通过。 $6.$ 代码实现(码丑勿喷): ```cpp #include<bits/stdc++.h> using namespace std; string s; int m,k,l,dp[1005][9005]; const int mod=1e9+7; int o(int x) { int res=0; while(x) { res+=x%10; x/=10; } return res; } bool pd(int x) { int i; for(i=1;i<=k;i++) { x=o(x); } if(x==m) { return true; } return false; } void solve() { int i,j,k,sum=s[0]-'0'; memset(dp,0,sizeof(dp)); for(i=0;i<s[0]-'0';i++) { dp[0][i]=1; } for(i=1;i<l;i++) { for(j=0;j<=9*(i+1);j++) { if(j-sum<s[i]-'0'&&j-sum>=0) { dp[i][j]++; } for(k=0;k<=9;k++) { if(k>j) { break; } dp[i][j]+=dp[i-1][j-k]; dp[i][j]%=mod; } } sum+=s[i]-'0'; } dp[l-1][sum]++; } int main() { ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL); int T,ans,i; cin>>T; while(T--) { cin>>s>>k>>m; if(k>4) { k=4; } k--; l=s.size(); solve(); ans=0; for(i=1;i<=9000;i++) { if(pd(i)) { ans+=dp[l-1][i]; ans%=mod; } } cout<<ans<<endl; } return 0; } ```