1. 程式人生 > >HDU3709 Balanced Number

HDU3709 Balanced Number

ret printf 多少 memset lan ems 如果 所有 距離

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3709

題目大意:

  定義一個數字上的某一個數位作為中樞,其他數位上的數乘上該數位到中樞的距離稱為該數位上的權值。

  問在 \([x,y]\) 中滿足下述條件的數有多少個:

  即能夠在數字上任取一個數位作為中樞,使得中樞左右所有數位的權值和相等。

知識點:  數位DP

解題思路:

  首先,對於每一個數(先不考慮 \(0\) ),如果它能找到滿足條件的中樞,那麽這種中樞只有一個。粗略證明:假設一個數有兩個滿足條件的不同位置的中樞,設為 \(p_1\), \(p_2\),\(p_1<p_2\),則 \(p_1\) 對應的左邊的權值和必定小於或等於 \(p_2\) 對應的左邊權值和,\(p_1\) 對應的右邊的權值和必定大於或等於 \(p_2\) 對應的右邊權值和,這兩者都相等當且僅當這個數為 \(0\),但我們暫時不考慮 \(0\),故假設不成立,原命題得證。

  基於以上的結論,我們可以枚舉中樞的位置,各自走一次 \(DFS\) 即可得出答案。

  另,無論中樞的位置在哪裏,\(0\) 顯然都會被計為滿足條件,故要註意去重。

AC代碼:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 ll dp[20][20][10000];   //dp[第幾位是中點][位置][sum值]
 6 int a[20];
 7 ll dfs(int pos,int zhong,int sum,bool limit){
 8     if(pos==-1)
9 return sum==0?1:0; 10 if(sum<0) return 0; 11 if(!limit&&dp[zhong][pos][sum]!=-1) return dp[zhong][pos][sum]; 12 int up=limit?a[pos]:9; 13 ll ans=0; 14 for(int i=0;i<=up;i++){ 15 int tsum=(pos-zhong)*i+sum; 16 ans+=dfs(pos-1,zhong,tsum,limit&&i==a[pos]);
17 } 18 if(!limit) dp[zhong][pos][sum]=ans; 19 return ans; 20 } 21 ll solve(ll x){ 22 if(x<0) return 0; 23 int pos=0; 24 while(x){ 25 a[pos++]=x%10; 26 x/=10; 27 } 28 ll ret=0; 29 for(int i=0;i<pos;i++){ 30 ret+=dfs(pos-1,i,0,true); 31 ret--; 32 } 33 return ret+1; 34 } 35 int main(){ 36 memset(dp,-1,sizeof(dp)); 37 int T; 38 ll x,y; 39 scanf("%d",&T); 40 while(T--){ 41 scanf("%lld%lld",&x,&y); 42 printf("%lld\n",solve(y)-solve(x-1)); 43 } 44 return 0; 45 }

HDU3709 Balanced Number