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 }
View Code

 

posted @ 2017-07-01 19:49  HuaZhang  阅读(181)  评论(0编辑  收藏  举报