bzoj1799 数位dp

HYSBZ - 1799

题意:给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。

思路:数位dp,比较容易想到是数位dp,关键是dp式比较难想到,数位dp说到底是一个记忆化搜索的过程,dp式是一个记忆数组,对于一类数来说,对应了一个dp式,并且他们的答案是一样的,那么可以通过只对一个经行搜索然后得到全部的答案,这其实就是一个状态,这个状态首先要保证与其他状态没有交集,并且要保证状态数不能过多,否则记忆化效果不好,比如1e18个数用1e5个状态来表示显然可以大大降低复杂度,时间上是没有问题的,但是如果状态答道了1e15就是一个非常糟糕的状态表示了,这个题的难点就是找状态,dp[pos][sum][v],第一维表示数位不用说,第二维表示前pos位的数位和,v表示这个数%mod的值,这个mod是枚举的,从1-162枚举, 比如 123xxxx枚举mod=5对应的dp式为dp[4][6][123%5],显然对于前3位和为6并且模的结果为3的状态的所有数来说答案是一样的,这里有一点,这里说的”答案“ 是指前几位已经确定,后面几位不确定,但是由已确定的前几位可以推出后面几位不确定的所有情况中可行的情况,比如123xx 一共存在100种可能性,其中12345是可行的,而12346是不可行的

AC代码:

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=1e5+100;

ll dp[18][162][162], bit[20];
ll dfs(int limit, int pos, int sum, int v, int mod){
    if(sum+pos*9+9<mod || sum>mod) return 0;
    if(pos==-1) return sum==mod && v==0;
    if(dp[pos][sum][v]!=-1 && !limit) return dp[pos][sum][v];
    int up=limit?bit[pos]:9;
    ll ans=0;
    for(int i=0; i<=up; ++i){
        ans+=dfs(limit&&i==bit[pos], pos-1, sum+i, (v*10+i)%mod, mod);
    }
    if(!limit) dp[pos][sum][v]=ans;
    return ans;
}

ll solve(ll x){
    int p=0;
    while(x){
        bit[p++]=x%10;
        x/=10;
    }
    ll ret=0;
    for(int i=1; i<=p*9; ++i){
        mem(dp,-1);
        ret+=dfs(1,p-1,0,0,i);
    }
    return ret;
}

int main(){
    ll a,b;
    scanf("%lld%lld",&a, &b);
    printf("%lld\n",solve(b)-solve(a-1));
    return 0;
}
时间: 2024-11-04 19:54:05

bzoj1799 数位dp的相关文章

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

先讲下个人对于数位DP的看法吧... 挺难理解的 首先需要明白的一点:前缀和很重要 其次:必须用到记忆化搜索(本人蒟蒻,必须要用这种方法降低难度) 然后呢,需要判断约束的条件:(1.前缀0(有时需要,有时不需要):2.数位的取值(基本都需要)) 比如这道题,乍一看无思路,然后呢.... 就会出现很神奇的事情 大胆尝试(第一次)3维(题解本来是4维的...) 居然就XJB A了... 略显蛋疼... 回归正题*2: 本题的状态有些难找,但是由于数位最多的也只有pos,所以就可枚举所有的数位和...

数位dp初探

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

数位DP复习小结

之前学数位dp的时候底子没打扎实 虚的要死 这次正好有时间……刷了刷之前没做的题目 感觉自己脑洞不太够……比较经典的题或者见过的类似模型就能自己推出来,但是没有见过的模型就虚的要死(比如二进制数位DP) 感谢WQ的帮助,让我对数位DP的理解逐渐加深 那么我们总结一下这次做的题目…… bzoj4521 记忆化搜索即可,水爆 1 #include <cstring> 2 #include <cstdio> 3 using namespace std; 4 #define RG regi

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【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

hdu 5898 odd-even number 数位DP

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 716    Accepted Submission(s): 385 Problem Description For a number,if the length of continuous odd digits is even and the length