来记录下解题思路:
坑点:long long型数据取模会TL
这题主要是用了数位dp的模板,主要的难点在于,枚举出这个数字所有数位的和的可能情况。
#include<bits/stdc++.h> using namespace std; int T; long long ans; int dp[17][120][120];//dp[pos][pre][ans] pre代表前面数字各个数位的和,ans代表目前的结果 int a[20]; int len; long long dfs(int pos,int pre,int limit,int cnt,int mod)//long long型号,否则不能过 { if(pre>mod) return 0;当前的数位和大于预期的数位和,返回0. if(pos==len) { if(pre==mod&&cnt==0) return 1;//当前数位和等于预期的数位和,且这个数能整除数位和,返回1 else return 0; } if(!limit&&dp[pos][pre][cnt]!=-1) { return dp[pos][pre][cnt]; } int up=limit?a[pos]:9; long long ret=0; for(int i=0;i<=up;i++) { ret+=dfs(pos+1,pre+i,limit&&(i==a[pos]),(cnt*10+i)%mod,mod); } if(!limit) dp[pos][pre][cnt]=ret; return ret; } void init(string str) { len=str.size(); for(int i=0;i<len;i++) { a[i]=str[i]-'0'; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>T; for(int i=1;i<=T;i++) { ans=0; string h; cin>>h; init(h); for(int j=1;j<=9*len;j++) { memset(dp,-1,sizeof(dp));//每次都要重置一次 ans+=dfs(0,0,1,0,j);//每次默认最后的各位和的结果是j } printf("Case %d: %lld\n",i,ans); } }