1. 程式人生 > >HDU 3709 Balanced Number 求區間內的滿足是否平衡的數量 (數位dp)

HDU 3709 Balanced Number 求區間內的滿足是否平衡的數量 (數位dp)

平衡數的定義是指,以某位作為支點,此位的左面(數字 * 距離)之和 與右邊相等,距離是指某位到支點的距離;

題意:求區間內滿足平衡數的數量 ; 

分析:很好這又是常見的數位dp , 不過不同的是我們這次需要列舉是哪個位置是平衡點 , 一開始我是想說搜尋到最後以為 ,然後得到這個數的位數 ,在判斷平衡位置 , 想到這樣的話 , 這就說明了我對數位dp 還是不太熟悉的 ,因為這樣的話dfs() 裡面的sum , emmm是找不到狀態的 ;

正解: 依然是列舉平衡點的位置  ,這個思路沒有問題 , 但是這個卻是在so(_) 函式裡面列舉 ,啊這樣就妙不可言了, 這樣的話只要我們在dfs()裡面增加變數 k ,表示是平衡點的位置 , 那這樣的話我的sum 就是記錄 從左到右的貢獻 , 因為是從左到右的列舉 , 左邊加, 右邊減 , 所以是不是sum<0 , 就肯定是不行的嘛 ;哦!還有一個重點 ,因為0也是平衡數來的 , 所以我們這樣的列舉平衡點就加了ans-1 次0 的貢獻 ,這裡巨坑一開始沒有想到,其他程式碼打出來了 , 答案不對 ,然後找程式的錯誤 ,其實這裡是關鍵來的

#include<stdio.h>
#include<string.h>
#include<cmath>
using namespace std ;
#define ll long long
ll dp[20][20][2002];
ll a[20];
ll dfs(int pos , int k , int  sum , bool limit)
{
    if(pos==-1)
    return sum==0;
    if(sum<0)
    return 0;
    if(!limit && dp[pos][k][sum]!=-1
) return dp[pos][k][sum]; int up=limit?a[pos]:9; ll ans=0; for(int i=0 ; i<=up ; i++) { ans+=dfs(pos-1,k,sum+(pos-k)*i,limit&&i==a[pos]); } if(!limit) dp[pos][k][sum]=ans; return ans; } ll so(ll x) { int ans=0; ll sum=0; while(x) { a[ans
++]=x%10; x/=10; } for(ll i=0 ; i<ans ; i++) sum+=dfs(ans-1,i,0,1); return sum-(ans-1); } int main( ) { int t; memset(dp,-1,sizeof(dp)); scanf("%d",&t); while(t--) { ll l,r; scanf("%lld%lld",&l,&r); printf("%lld\n",so(r)-so(l-1)); } }
View Code