HDU 3709 Balanced Number 数位dp

来源:互联网 发布:校园全覆盖网络弊端 编辑:程序博客网 时间:2024/06/06 05:48

Balanced Number

Description

A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit. When a pivot is placed at some digit of the number, the distance from a digit to the pivot is the offset between it and the pivot. Then the torques of left part and right part can be calculated. It is balanced if they are the same. A balanced number must be balanced with the pivot at some of its digits. For example, 4139 is a balanced number with pivot fixed at 3. The torqueses are 4*2 + 1*1 = 9 and 9*1 = 9, for left part and right part, respectively. It’s your job
to calculate the number of balanced numbers in a given range [x, y].

Input

The input contains multiple test cases. The first line is the total number of cases T (0 < T ≤ 30). For each case, there are two integers separated by a space in a line, x and y. (0 ≤ x ≤ y ≤ 10 18).

Output

For each case, print the number of balanced numbers in the range [x, y] in a line.

Sample Input

2
0 9
7604 24324

Sample Output

10
897

题意:求出在[l,r]中,有多少个数至少存在1个位置作为中心位置,使得左右的力矩相等。

题解:
用dp[i][j][k]表示第i位,中心位置为第j位,和为k的结果。
然后枚举中心位置。一个小优化:sum<0的时候直接return 0;因为超过中心位置之后的数的贡献都为负,再计算下去只会越来越小。
注意:0,00,000这些结果都会被计入,但其实它们本身是一样的,所以最后的结果减去(cnt-1),即多计算的0的个数。
//我试过好多种方法,这种方法最简单最直接也最好理解
//好吧因为我想到的其他方法都不对
今天又是登不上hdu而改用vjudge的一天。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int N = 20;const int M = 1500 + 10;ll l,r;int a[N];ll dp[N][N][M];ll dfs(int pos,int point,int sum,bool limit){    if(pos<=0) return sum==0;    if(sum<0) return 0;    if(dp[pos][point][sum]!=-1&&!limit) return dp[pos][point][sum];    int mx;if(limit) mx=a[pos];else mx=9;    ll ans=0;    for(int i=0;i<=mx;i++){        ans+=dfs(pos-1,point,sum+(pos-point)*i,limit&&i==mx);    }    if(!limit) dp[pos][point][sum]=ans;    return ans;}ll getans(ll x){    if(x<0) return 0;    int cnt=0;    while(x){        a[++cnt]=x%10;        x/=10;    }    ll ans=0;    for(int i=1;i<=cnt;i++) ans+=dfs(cnt,i,0,1);    return ans-(cnt-1);}int t;int main(){    scanf("%d",&t);    memset(dp,-1,sizeof(dp));       while(t--){       cin>>l>>r;       cout<<getans(r)-getans(l-1)<<endl;    }    return 0;}