hdu 3709 Balanced Number

http://acm.hdu.edu.cn/showproblem.php?pid=3709

数位dp,练模板好题。。

题目要求求出[x, y] 范围内的平衡数,

平衡数定义为:以数中某个位为轴心,两边的数的偏移量为矩,数位权重,使得整个数平衡。

当然,首先可以简化一下条件~,设Kp以p为支点平衡度;

Kp = sum(di*(i-p));  故△Kp = K(p+1) - Kp = -sum(di);

记 ps = K0  (以0为支点平衡度), s = sum(di);

所以条件存在Kp == 0等价为  s|ps.

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string>
 4 #include <algorithm>
 5 #include <string.h>
 6 #include <stdlib.h>
 7 #define LL long long
 8 using namespace std;
 9 
10 LL dp[20][1500][200];
11 int d[20];
12 
13 LL dfs(int p, int ps, int s, bool e){    
14         //ps: sum(di*i), s:sum(di) 
15     if(p == -1)    return (s==0 || ps%s==0);    //s|ps; 
16     if(!e && dp[p][ps][s]!=-1)    return dp[p][ps][s];
17     int u=e? d[p]: 9;
18     LL ans=0;
19     for(int i=0; i<=u; i++)
20         ans += dfs(p-1, ps+(s+i), s+i, e&&(i==u));
21     return e? ans: (dp[p][ps][s] = ans);
22 }
23 
24 LL f(LL x){
25     int p=0;
26     while(x){
27         d[p++] = x%10;
28         x /= 10;
29     }
30     return dfs(p-1, 0, 0, 1);
31 }
32 
33 int main()
34 {
35     int T;
36     cin >> T;
37     LL m, n;
38     memset(dp, -1, sizeof(dp));
39     while(T--){
40         cin >> m >> n;        
41         cout << f(n)-f(m-1) << endl;
42     }
43     
44     return 0;
45 }
46     
View Code

当然也可以直接做,枚举所有支点p,以及相应平衡度Kp ~

记ps表示平衡度Kp,   s表示支点p。

条件是  Kp == 0  。

hint:  支点p不同时,Kp一定不同,除非△Kp ==0;

     故只有x == 0 时, 按支点划分,会重复。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string>
 4 #include <algorithm>
 5 #include <string.h>
 6 #include <stdlib.h>
 7 #define LL long long
 8 using namespace std;
 9 
10 LL dp[20][1500][20];
11 int d[20];
12 
13 LL dfs(int p, int ps, int s, bool e){    
14     if(p == -1)    return (ps==0);
15     if(ps < 0)    return 0;     //平衡度<0, 必不满足, 剪枝。 
16     if(!e && dp[p][ps][s]!=-1)    return dp[p][ps][s];
17     int u=e? d[p]: 9;
18     LL ans=0;
19     for(int i=0; i<=u; i++)
20         ans += dfs(p-1, ps+i*(p-s), s, e&&(i==u));
21     return e? ans: (dp[p][ps][s] = ans);
22 }
23 
24 LL f(LL x){
25     int p=0;
26     while(x){
27         d[p++] = x%10;
28         x /= 10;
29     }
30     LL ans = 0;
31     for(int i=0; i<p; i++)    //按支点划分 
32         ans += dfs(p-1, 0, i, 1);
33     return ans-p+1;        //除去重复的0000000(p个0)的情况!! 
34 }
35 
36 int main()
37 {
38     int T;
39     cin >> T;
40     LL m, n;
41     memset(dp, -1, sizeof(dp));
42     while(T--){
43         cin >> m >> n;        
44         cout << f(n)-f(m-1) << endl;
45     }
46     
47     return 0;
48 }
View Code
原文地址:https://www.cnblogs.com/KimKyeYu/p/3426828.html