HDU_3709 Balanced Number 数位dp

http://acm.hdu.edu.cn/showproblem.php?pid=3709

题意:

求[x , y]内的平衡数的个数。 0<=x ,y <=10^18

思路:

数位dp。先枚举pivot点,然后逐位进行确定,为了便于处理,dp的时候我们将左右力矩合在一起考虑,即左边的力矩是正的,右边的力矩用负的表示。状态为:dp[pos][ pivot ][ sum ]表示后面pos位在不受大小限制的情况下,且支点在pivot点,力矩和为sum时的种数。

代码:

#include <stdio.h>
#include <string.h>

typedef __int64 LL ;
LL x, y ;
int digit[22] , pos ;
LL dp[22][22][1600] ;

LL dfs(int pos, int pivot , int s , int limit ){
    if( pos == 0 )  return ( s == 0 ) ;
    if( s < 0 ) return 0  ;
    if( !limit && dp[pos][pivot][s] != -1 ) return dp[pos][pivot][s] ;
    int end = limit ? digit[pos] : 9 ;
    LL res =  0 ;
    int n_s ;
    for(int i=0;i<=end;i++){
        n_s = s + ( pos - pivot) * i ;
        res += dfs( pos-1 , pivot , n_s , limit&(i==end) ) ;
    }
    if( !limit )    dp[pos][pivot][s] = res ;
    return res ;
}

LL cal( LL n ){
    if( n==-1 ) return  0 ;
    if( n==0 )  return  1 ;
    pos = 0 ;   LL tmp = n ;
    while( tmp ){
        digit[ ++pos ] = tmp % 10 ; tmp /= 10 ;
    }

    LL sum = 0 ;
    memset( dp , -1 , sizeof(dp) );
    for( int i=pos;i>=1;i-- ){
        sum += dfs( pos , i , 0 , 1 ) ;
    }
    sum -= ( pos - 1 );
    return sum ;
}

int main(){
    int T ; scanf("%d",&T);
    for( int cas = 1 ; cas <= T ; cas ++ ){
        scanf("%I64d %I64d",&x,&y) ;
        printf("%I64d\n", cal(y) - cal(x-1) )  ;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值