HDOJ3709_Balanced Number

来源:互联网 发布:绿尾真假辨别技巧知乎 编辑:程序博客网 时间:2024/06/07 17:01

题目链接:HDOJ3709

题意:给定区间【A,B】,求区间内的平衡数。定义是:选取某一个数字作为支点,各个数字到该数字的距离为力矩,使得杠杆平衡。如3218这个数,以1为支点时,3距离为2,2距离为1,左边之和为8,后边之和也为8,为平衡数


数位DP思想也很简单:既然不知道支点是那个点,枚举一发。既然不知道是否平衡,那么每个都来算

所以定义:dp【pos】【x】【st】:pos指当前枚举的数位,x指的是支点在哪,st指当前枚举的数位计算得到的和

要注意到st不能为负数(不然数组处理起来有问题),要特判


另外,这个题是做到的第一个前导0有影响的题

如果数为0,是可以的(既符合题意,又确实存在这个数)

如果数为00,是不可以的(符合题意,是平衡数,但是这个数跟0不是一个吗)

所以这个数有几位,数位最大是len,就会多统计了len-1个,在计算的时候要除掉


剩下的都是套路:

__int64 dp[30][30][2050];int digit[30];int t;__int64 m,n;__int64 dfs(int pos,int x,int st,bool flag){if (pos==0) return st==0;if (st<0) return 0;if (flag&&dp[pos][x][st]!=-1) return dp[pos][x][st];int num=flag?9:digit[pos];__int64 ans=0;for(int i=0;i<=num;i++){int tmp=st+i*(pos-x);ans+=dfs(pos-1,x,tmp,flag||i<num);}if (flag) dp[pos][x][st]=ans;return ans;}__int64 calc(__int64 x){if (x<0) return 0;int len=0;__int64 ans=0;while(x){digit[++len]=x%10;x/=10;}for(int i=1;i<=len;i++)ans+=dfs(len,i,0,0);return ans-len+1;//return ans;}int main(){//input;memset(dp,-1,sizeof(dp));scanf("%d",&t);while(t--){scanf("%I64d%I64d",&m,&n);printf("%I64d\n",calc(n)-calc(m-1));}return 0;}


0 0