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
当然也可以直接做,枚举所有支点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 }