UVA11361 Investigating Div-Sum Property(数位dp)

转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

题目意思:问在区间[A,B]有多少个数不仅满足自身是k的倍数,而且其各个位数上的和(十进制)也是k的倍数。

分析:数位dp

首先注意到1+9*9=82,即k最大只能是82,所以,在大于82是直接输出答案为0;

dp[i][j][t]——表示从左往右递推到第i位时(后面所有位数用0填充),各个位数上的和mod k等于j,且这个数mod k等于t时的方案数

状态转移方程为dp[i][j][t]=∑dp[i-1][((j-x)%k+k)%k][((t-x*10^i)%k+k)%k]  (x=0,1,2,……,9)

注意递推的时候相应的位次上是有限制的,并且不要忘记判断其自身

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 int k;
 5 int d[10];
 6 int p[11];
 7 int dp[10][110][110];
 8 int dfs(int size,int n,int m)
 9 {
10     if(!size)
11     {
12         if(n==0&&m==0)return 1;
13         return 0;
14     }
15     if(dp[size][n][m]>=0)return dp[size][n][m];
16     dp[size][n][m]=0;
17     for(int i=0;i<10;i++)
18     {
19         dp[size][n][m]+=dfs(size-1,((n-i)%k+k)%k,((m-i*p[size-1])%k+k)%k);
20     }
21     return dp[size][n][m];
22 }
23 int solve(int num)
24 {
25     int n=0,m=0,size=0,ans=0;
26     if(num==0)return 1;
27     while(num)
28     {
29         d[size++]=num%10;
30         temp+=d[size-1];
31         num/=10;
32     }
33     d[0]++;
34     for(int i=size-1;i>=0;i--)
35     {
36         for(int j=0;j<d[i];j++)
37         {
38             ans+=dfs(i,((k-n-j)%k+k)%k,((k-m-j*p[i])%k+k)%k);
39         }
40         n=(n+d[i])%k;
41         m=(m+d[i]*p[i])%k;
42 
43     }
44     return ans;
45 
46 }
47 
48 int main()
49 {
50     ios::sync_with_stdio(false);
51     p[0]=1;
52     for(int i=1;i<10;i++)p[i]=p[i-1]*10;
53     int a,b,t;
54     cin>>t;
55     while(t--)
56     {
57         cin>>a>>b>>k;
58         if(k>82)cout<<0<<endl;
59         else
60         {
61             memset(dp,-1,sizeof(dp));
62             cout<<solve(b)-solve(a-1)<<endl;
63         }
64     }
65     return 0;
66 }
View Code

 

转载于:https://www.cnblogs.com/fraud/p/4085902.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值