UVA 11361 Investigating Div-Sum Property
题目链接:UVA-11361
题意:给定a,b,k。求在a和b之间,有多少数字满足自身是k的倍数,且该数字的各数位和也是k的倍数。
思路:典型的数位dp,需要注意的是各数位和m1的范围,否则无法记忆化,可以熟悉一下数位dp的模板。
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 typedef long long LL; 9 10 LL k; 11 LL a[20]; 12 LL ten[20]; 13 LL dp[20][200][10010];//不同题目状态不同 14 LL dfs(LL pos,LL m1,LL m2,bool limit) 15 { 16 if(m1>=200) return 0; 17 if(pos==-1) 18 { 19 if(m1==0 && m2==0) return 1; 20 return 0; 21 } 22 if(!limit && dp[pos][m1][m2]!=-1) return dp[pos][m1][m2]; 23 LL up=limit?a[pos]:9; 24 LL ans=0; 25 for(LL i=0;i<=up;i++) 26 ans+=dfs(pos-1,((m1-i)%k+k)%k,((m2-i*ten[pos])%k+k)%k,limit && i==a[pos]); 27 if(!limit) dp[pos][m1][m2]=ans; 28 return ans; 29 } 30 LL solve(LL x) 31 { 32 LL pos=0; 33 while(x) 34 { 35 a[pos++]=x%10; 36 x/=10; 37 } 38 return dfs(pos-1,0,0,true); 39 } 40 int main() 41 { 42 #ifdef LOCAL 43 freopen("in.txt","r",stdin); 44 freopen("out.txt","w",stdout); 45 #endif 46 ten[0]=1; 47 for(int i=1;i<20;i++) ten[i]=ten[i-1]*10; 48 LL t; 49 scanf("%lld",&t); 50 for(LL tt=1;tt<=t;tt++) 51 { 52 memset(dp,-1,sizeof(dp)); 53 LL a,b; 54 scanf("%lld%lld%lld",&a,&b,&k); 55 printf("%lld\n",solve(b)-solve(a-1)); 56 } 57 return 0; 58 }