HDU 3709 Balanced Number

Balanced Number

题意: 平衡数:存在该数中以一个数字为支点(pivot),点的"力矩"为该点到支点的距离乘以该点的值,而平衡指的是支点两侧的力矩和相等

思路:

  易知当支点相同时,只要前面的力矩相等,那么就可以建立相同的子结构。那么dp中就要把支点加进去,同时力矩也要加进去,外加位置就是三维。原本分析认为位置可以不加,但是发现少计算了很多。同时看static里面,memory用得最小的也是将近小了20倍,觉得这一维也是可以去掉的。以后想到在贴出来吧!

  支点的转化:原本想直接在dfs里面看看能否设置为一个pivot动一个不动,但是没搞出来,之后就直接枚举了...每次数位DP都要看看前置0的影响。这道题每一个支点都会有一个0,所以减去重复的即可。

#include<bits/stdc++.h>
using namespace std;
#define MS1(a) memset(a,-1,sizeof(a))
#define MS0(a) memset(a,0,sizeof(a))
typedef long long ll;
int bit[23];
ll dp[20][1800][20];
ll dfs(int pos,int val,int pivot,bool edge)
{
    if(val < 0) return 0;
    if(pos == -1) return val == 0;
    if(!edge && dp[pos][val][pivot] >= 0) return dp[pos][val][pivot];
    int end = edge ? bit[pos] : 9;
    ll ans = 0;
    for(int i = 0;i <= end;i++){
        ans += dfs(pos - 1,val+i*(pos - pivot),pivot,edge&&(i==end));
    }
    if(!edge) dp[pos][val][pivot] = ans;
    return ans;
}
ll calc(ll n)
{
    if(n == -1) return 0;
    int tot = 0;
    while(n){
        bit[tot++] = n%10;
        n /= 10;
    }
    ll ans = 0;
    for(int i = tot - 1;i >= 0;i--)
        ans += dfs(tot - 1,0,i,true);
    return ans - tot + 1;
}
int main()
{
    MS1(dp);
    int T;
    scanf("%d",&T);
    while(T--){
        ll L,R;
        scanf("%I64d%I64d",&L,&R);
        printf("%I64d
",calc(R) - calc(L-1));
    }
}
View Code
原文地址:https://www.cnblogs.com/hxer/p/5177455.html