hdu3709Balanced Number【数位dp】

F.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts
Problem Archive
Realtime Judge Status
Authors Ranklist
 
      C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests

Balanced Number

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 3549    Accepted Submission(s): 1630


Problem 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
 

Author
GAO, Yuan
 

Source


憋了一中午才A掉的题==也算是数位dp中比较经典的了

说题意:给定已知数字串,要求以某个数字为中心的两侧力矩和相等的个数,我们考虑三个与结果相关的量:当前枚举的到的长度、轴的位置、力矩和,分别作为dp的三维

flag用以标记最大位是否使用,注意sum<0退出;pos=0时候,如果sum=0那么方法数相当于+1,因要求是==0嘛,也就是说,在递归的过程中,pos center的相对位置不定,pos挪到右边依旧是pos-center那么就是加上负值了== 到最后flag=0时,我们可以认为当前情况遍历完毕,才可以为dp赋值

好好理解这个题才能做出来下一个poj3252呢--

/************
hdu3709
2016.3.11
31MS	22860K	1075 B	C++
************/
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long dp[30][30][3000];
int num[30];
long long dfs(int pos,int center,int sum,bool flag)
{
    if(pos==0) return sum==0;
    if(sum<0) return 0;
    if(!flag&&dp[pos][center][sum]!=-1) return dp[pos][center][sum];
    long long ans=0;
    int maxn=flag?num[pos]:9;
    for(int i=0;i<=maxn;i++)
    {
        ans+=dfs(pos-1,center,sum+i*(pos-center),i==maxn&&flag);
    }//pos-center
    if(!flag) dp[pos][center][sum]=ans;
    return ans;
}
long long cal(long long x)
{
    long long ans=0;
    int pos=0;
    while(x)
    {
        num[++pos]=x%10;
        x/=10;
    }
    for(int i=1;i<=pos;i++)
    ans+=dfs(pos,i,0,1);
    return ans-pos+2;
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int t;
    long long n,m;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d%I64d",&n,&m);
        printf("%I64d\n",cal(m)-cal(n-1));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值