zoj4100 Balanced Number 数位DP

题目的意思是询问[A,B]区间内,有多少个Balanced Number,每个Balanced Number符合以下条件:

将一个数按位拆分,存在一个位置mid,使得sigma(val[i]*(mid-i))=sigma(val[j]*(j-mid)) {i<mid,j>mid}

然后就是一脸数位dp的样子...

一开始的想法是枚举mid,因为分析了一下,除0以为的某个Balanced Number,一定只有一个位置符合条件。

然后接下来就脑残了,将数字拆成两半来dp,然后合并的时候死活合并不了。后来想了一下,瞬间觉得自己脑残了,根本就不用拆分。直接从后往前dp就行,没想好代码怎么写,就开始敲,真的很忧伤..

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<iostream>

using namespace std;

#define For(i,forN) for(int i=0;i<forN;i++)
#define sf  scanf
#define pf  printf
#define mp  make_pair

#define _clr(x,y)   memset(x,(y),sizeof(x))

typedef long long LL;

const int Maxn=21,Maxl=1400,Maxe=Maxl;
LL dp[2][Maxn][Maxl];
int num[Maxn],len;

typedef long long LL;
LL A,B;

LL getAns(int mid)
{
    _clr(dp,0);
    dp[0][len][0]=1;//0表示x<=val,1表示x>val
    for(int i=len-1;i>=0;i--)
    {
        int s=0,l=i-mid;
        for(int j=0;j<Maxe;j++)
        {
            for(int k=s;k<10;k++)
            {
                int tj=l*k+j;
                if(tj<Maxe && tj>=0)
                {
                    if(k<num[i])//那么x一定小于val
                    {
                        dp[0][i][tj]+=dp[0][i+1][j]+dp[1][i+1][j];
                    }
                    else if(k>num[i])//那么x一定大于val
                    {
                        dp[1][i][tj]+=dp[0][i+1][j]+dp[1][i+1][j];
                    }
                    else
                    {
                        dp[0][i][tj]+=dp[0][i+1][j];
                        dp[1][i][tj]+=dp[1][i+1][j];
                    }
                }

            }
        }
    }
    return dp[0][0][0];
}

LL cal(LL val)
{
    if(val<0)   return 0;
    if(val<10)  return val+1;
    len=0;
    while(val)
    {
        num[len++]=val%10;
        val/=10;
    }
    reverse(num,num+len);
    LL ans=0;
    for(int i=0;i<len;i++)
    ans+=getAns(i);
    return ans-len+1;
}

int main()
{
    int cas;
    cin>>cas;
    while(cas--)
    {
        cin>>A>>B;
        cout<<cal(B)-cal(A-1)<<endl;
    }
}
原文地址:https://www.cnblogs.com/CooCoo/p/3409171.html