手打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了,整个人也废了。。。。

时间: 2024-11-02 20:28:02

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

【POJ3208】传说中POJ最难的数位DP?(正解AC自动机,二解数位DP,吾异与之)

题意: 多组数据,每组求第n个包含'666'的数(不能断开),如1:666,2:1666,14:6667. 题解: AC自动机解法没去想,数位DP没学,这里有一种类似于数位DP,却又与数位DP不同,我称为数位树. 数位树: 将数n如线段树一样地拆分成多个小段,进行递归处理得出答案. 本题详(lue)解: 直接看每一位应该是什么数,然后n减去相应的数,使得在下一层转换为子问题"在开头有b个连续的6时,求第a个带'666'的数".就是如此简单,如此简单!!!! 代码来啦! #include

几道数位dp

hdu2089 不要62 /* ID: neverchanje PROG: LANG: C++11 */ #include<vector> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cstdio> #include<set> #include<queu

BZOJ 1799: [Ahoi2009]self 同类分布 ( 数位dp )

传送门   也不是很难,微坑的一点是dp数组在扫描每一次数位和的时候都要初始化, 因为没有存 用来mod的总数位和x 的位置... ... 然后这个dp的式子也稍微想了一下...还是练题太少... 1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7

数位dp初探

我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了很久TAT #include<cstring> #include<iostream> #include<cstdio> #include<queue> #include<cmath> #include<algorithm> #define

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task

HDU2089 不要62[数位DP]

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 36862    Accepted Submission(s): 13418 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可

CodeForces 55D Beautiful numbers(数位dp&amp;&amp;离散化)

题目链接:[kuangbin带你飞]专题十五 数位DP A - Beautiful numbers 题意 ps:第一道数位dp,题真好,虽然是参考大牛方法悟过才a,但仍收获不少. 求一个区间内的Beautiful numbers有多少个.Beautiful numbers指:一个数能整除所有组成它的非0数字. 例如15可以被1和5整除,所以15是Beautiful numbers. 思路 Beautiful numbers指:一个数能整除所有组成它的非0数字. 等同于 一个数能整除 所有组成它的

[bzoj1006][SCOI2009]windy数 (数位dp)

Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数. Sample Input [输入样例一] 1 10 [输入样例二] 25 50 Sample Output [输出样例一] 9 [输出样例二] 20 HINT [数据规模和约定] 100%的数据,满足 1 <= A <= B <= 2

hdu 4722 Good Numbers(初涉数位dp)

http://acm.hdu.edu.cn/showproblem.php?pid=4722 大致题意:若一个整数的各位数字之和是10的倍数,称这个数为"good number".给出区间[A,B],求出该区间内"good number"的数的个数. 第一道数位dp,折腾了半天才明白怎么回事. 设dp[site][mod]表示到第site位(由高位向低位)前面各位数字之和对10取余为mod的数的个数,进行记忆化搜索.有两个很重要的点,首先是变量up,表示是否到达边界