HDU3709 Balanced Number【数位DP】

题目链接:HDU3709 Balanced Number

题意:问区间[l,r]内平衡数的个数,平衡数是指选某一位作支点,左右两边每一位数值*力矩的和相等;

分析:dp[len][pos][sum]表示长度为len的数,当支点为pos时,力矩为sum的数的个数;转移是由长度为len-1的数+第len位转移而来,所以dp[len][pos][sum]+=dp[len-1][pos][sum+i*(pos-x)],i是第len位可能出现的数,这里不需要取abs,sum为0时说明平衡;

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[20][20][1800];
int num[20];
ll dfs(int len,int pos,int sum,bool flag)
{
    if (!len) return sum==0?1:0;
    if (sum<0) return 0;
    if (!flag && dp[len][pos][sum]!=-1) return dp[len][pos][sum];
    int mx=flag?num[len]:9;
    ll res=0;
    for (int i=0;i<=mx;i++) res+=dfs(len-1,pos,sum+i*(len-pos),flag && i==mx);
    if (!flag) dp[len][pos][sum]=res;
    return res;
}
ll solve(ll n)
{
    if (n<0) return 0;
    int len=0;
    for (;n;n/=10) num[++len]=n%10;
    ll sum=0;
    for (int i=1;i<=len;i++) sum+=dfs(len,i,0,true);
    return sum-(len-1);
}
int main()
{
    memset(dp,-1,sizeof(dp));
    int T;
    ll a,b;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld%lld",&a,&b);
        printf("%lld\n",solve(b)-solve(a-1));
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_43813163/article/details/102582752