HDU 3709 Balanced Number
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3709 Balanced Number相关的知识,希望对你有一定的参考价值。
- 题意: 平衡数:存在该数中以一个数为支点(pivot),点的"力矩"为该点到支点的距离乘以该点的值,而平衡指的是支点两侧的力矩和相等
- 思路:
- 易知当支点相同时,只要前面的力矩相等,那么就可以建立相同的子结构。那么dp中就要把支点加进去,同时力矩也要加进去,外加位置就是三维。原本分析认为位置可以不加,但是发现少计算了很多。同时看static里面,memory用得最小的也是将近小了20倍,觉得这一维也是可以去掉的。以后想到在贴出来吧!
2.支点的转化:原本想直接在dfs里面看看能否设置为一个pivot动一个不动,但是没搞出来,之后就直接枚举了...每次数位DP多要看看前置0的影响。这道题每一个支点都会有一个0,所以减去重复的即可。
#include<bits/stdc++.h> using namespace std; #define MS1(a) memset(a,-1,sizeof(a)) #define MS0(a) memset(a,0,sizeof(a)) typedef long long ll; int bit[23]; ll dp[20][1800][20]; ll dfs(int pos,int val,int pivot,bool edge) { if(val < 0) return 0; if(pos == -1) return val == 0; if(!edge && dp[pos][val][pivot] >= 0) return dp[pos][val][pivot]; int end = edge ? bit[pos] : 9; ll ans = 0; for(int i = 0;i <= end;i++){ ans += dfs(pos - 1,val+i*(pos - pivot),pivot,edge&&(i==end)); } if(!edge) dp[pos][val][pivot] = ans; return ans; } ll calc(ll n) { if(n == -1) return 0; int tot = 0; while(n){ bit[tot++] = n%10; n /= 10; } ll ans = 0; for(int i = tot - 1;i >= 0;i--) ans += dfs(tot - 1,0,i,true); return ans - tot + 1; } int main() { MS1(dp); int T; scanf("%d",&T); while(T--){ ll L,R; scanf("%I64d%I64d",&L,&R); printf("%I64d\n",calc(R) - calc(L-1)); } }
以上是关于HDU 3709 Balanced Number的主要内容,如果未能解决你的问题,请参考以下文章