zoukankan      html  css  js  c++  java
  • 【sgu390】数位dp

    这题其实就是不断地合并子树,跟前面例一的思想是一样的。

    这个打法我觉得非常优美啊(学别人的),为什么要搞lim1和lim2呢?

    是因为在区间lim1~lim2之外的都是没有用的,但是我们f[h][sum][rem]里存的是一棵完整的h层的树,所以被lim1和lim2限制的就不存进去了。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const LL N=1100;
    LL l,r,K;
    struct node{
        LL a,b;
        bool bk;
        node()
        {
            bk=0;a=0;b=0;
        }
    }f[20][N][N];
    LL dl[20],dr[20];
    
    void mercy(node &x,node y){x.a+=y.a;x.b=y.b;}
    
    node dp(LL h,LL sum,LL rem,LL lim1,LL lim2)
    {
        node ans;
        ans.a=0;ans.b=rem;
        if(f[h][sum][rem].bk && !lim1 && !lim2) return f[h][sum][rem];
        if(h==0)
        {
            if(sum+rem>=K) ans.a=1,ans.b=0;
            else ans.a=0,ans.b=sum+rem;
        }
        else 
        {
            LL x=lim1 ? dl[h] : 0;
            LL y=lim2 ? dr[h] : 9;
            for(LL i=x;i<=y;i++)
            {
                mercy(ans,dp(h-1,sum+i,ans.b,(lim1&(i==x)),(lim2&(i==y))));
            }
        }
        if(!lim1 && !lim2) f[h][sum][rem]=ans,f[h][sum][rem].bk=1;
        return ans;
    }
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("me.out","w",stdout);
        scanf("%lld%lld%lld",&l,&r,&K);
        LL x;
        memset(dl,0,sizeof(dl));
        memset(dr,0,sizeof(dr));
        x=0;while(l) {dl[++x]=l%10;l/=10;}
        x=0;while(r) {dr[++x]=r%10;r/=10;}
        printf("%lld
    ",dp(18,0,0,1,1).a);
        return 0;
    }
  • 相关阅读:
    FLASH开发[00]
    slickedit使用小技巧
    网络编程[34]
    网络编程[39]
    网络编程[41]
    网络编程[37]
    网络编程[32]
    网络编程[35]
    Apache安装和配置
    网络编程[40]
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5968690.html
Copyright © 2011-2022 走看看