zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    XCode快捷键 转
    [iOS] UIView的clipsTobounds属性
    ios 重用UI部分代码的好方法(再也不用为局部变量的命名而烦恼啦!)
    symbol(s) not found for architecture armv7
    duplicate symbol _main in: / linker command failed with exit code 1
    xcode4.3.2 arc模式下导入非arc的文件 转
    objective-c block 详解 转
    将asi-http-request引入到ARC工程需要做的 转
    浅用block 转
    在Xcode4.5中禁用ARC(Automatic Referencing Counting) 转
  • 原文地址:https://www.cnblogs.com/CooCoo/p/3409171.html
Copyright © 2011-2022 走看看