• 手打AC的第2道数位DP:BZOJ1799: [Ahoi2009]self 同类分布


    先讲下个人对于数位DP的看法吧。。。

    挺难理解的

    首先需要明白的一点:前缀和很重要

    其次:必须用到记忆化搜索(本人蒟蒻,必须要用这种方法降低难度)

    然后呢,需要判断约束的条件:(1.前缀0(有时需要,有时不需要);2.数位的取值(基本都需要))

    比如这道题,乍一看无思路,然后呢。。。。

    就会出现很神奇的事情

    大胆尝试(第一次)3维(题解本来是4维的。。。)

    居然就XJB A了...

    略显蛋疼。。。

    回归正题*2;

    本题的状态有些难找,但是由于数位最多的也只有pos,所以就可枚举所有的数位和。。。

    记录几个状态(sum(数位和,最后必须变回0),val(表示数的值),以及数位即可)

    代码如下


    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    using namespace std;
    
    ll dp[20][180][180],n,m,a[1005];
    ll dfs(int pos,int sum,int val,int mod,int limit){
        if (sum-9*(pos+1)>0) return 0;
        if (pos==0) return sum==0 && val==0;
        if (!limit && dp[pos][sum][val]!=-1) return dp[pos][sum][val];
        int up=limit?a[pos]:9;
        ll ans=0;
        for (int i=0; i<=up; i++)
        {
            if (sum-i<0) break;
            ans+=dfs(pos-1,sum-i,(val*10+i)%mod,mod,limit && a[pos]==i);
        }
        if (!limit) dp[pos][sum][val]=ans;
        return ans;
    }
    
    ll solve(ll x){
        ll pos=0;
        while (x){
            a[++pos]=x%10;
            x/=10;
        }
        ll ans=0;
        for (int i=1; i<=pos*9; i++)
        {
            memset(dp,-1,sizeof(dp));
            ans+=dfs(pos,i,0,i,1);
        }
        return ans;
    }
    
    int main(){
        scanf("%lld%lld",&n,&m);
        printf("%lld",solve(m)-solve(n-1));
        return 0;
    }

    总结:

      打了一天的数位DP了,整个人也废了。。。。

  • 相关阅读:
    推荐系统相关知识
    关于hive核心
    关于hive的基础
    立个flag
    关于数据增强——文本增强
    .NET Core 实践:事件通知和异步处理
    .NET Core 实践:微服务架构的优点
    C#一定比C++性能差?当然不!破除迷信,从我做起!
    Visual Studio Code 搭配 Docker 一键搭建golang开发环境
    单例双重检查引发的资源竞争/数据竞争
  • 原文地址:https://www.cnblogs.com/leomessi-/p/7576939.html
Copyright © 2020-2023  润新知