数位dp题集
题集见大佬博客
不要62
入门题,检验刚才自己有没有看懂
注意一些细节。
的确挺套路的
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; const int MAXN = ;
int a[MAXN], dp[MAXN][MAXN][MAXN], len; //dp数组记录除了lead和limit以外其他的东西 int dfs(int pos, int pre, int lead, int sum, int limit)
{
if(pos > len) return sum;
if(dp[pos][pre][sum] != - && !limit && !lead) return dp[pos][pre][sum]; //记忆化的时候记得limit和lead
int l = limit ? a[len-pos+] : , res = ; //注意是倒序存的,所以是len-pos+1
_for(i, , l)
{
if(!i && lead) res += dfs(pos + , pre, lead, sum, limit && (i == l)); //先看是不是前导0
else if(i && lead) res += dfs(pos + , i, , sum | (i == ), limit && (i == l)); //看是不是第一位
else res += dfs(pos + , i, , sum | (i == ) | (pre == && i == ), limit && (i == l)); //正式处理
}
return (!limit && !lead) ? dp[pos][pre][sum] = res : res; //记忆化的时候记得limit和lead
} int part(int x)
{
if(x < ) return ; //0的处理
memset(dp, -, sizeof(dp));
len = ; int t = x;
for(; x; x /= ) a[++len] = x % ;
return t - dfs(, , , , );
} int main()
{
int n, m;
while(scanf("%d%d", &n, &m))
{
if(n == && m == ) break;
printf("%d\n", part(m) - part(n - ));
}
return ;
}
P2657 [SCOI2009]windy数
继续套路
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; const int MAXN = ;
int a[MAXN], dp[MAXN][MAXN][MAXN], len; int dfs(int pos, int pre, int ans, int lead, int limit)
{
if(pos > len) return ans;
if(dp[pos][pre][ans] != - && (!limit && !lead)) return dp[pos][pre][ans];
int l = limit ? a[len-pos+] : , res = ;
_for(i, , l)
{
if(!i && lead) res += dfs(pos + , pre, ans, lead, limit & (i == l));
else if(i && lead) res += dfs(pos + , i, ans, , limit & (i == l));
else res += dfs(pos + , i, ans & (abs(i - pre) >= ), , limit & (i == l));
}
return (!limit && !lead) ? dp[pos][pre][ans] = res : res;
} int part(int x)
{
if(x == ) return ;
memset(dp, -, sizeof(dp));
len = ;
for(; x; x /= ) a[++len] = x % ;
return dfs(, , , , );
} int main()
{
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", part(b) - part(a - ));
return ;
}
P2602 [ZJOI2010]数字计数
第一次这么轻松做出紫题
一样套模板,爽啊
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; typedef long long ll;
const int MAXN = ;
const int MAXM = 1e6 + ;
ll dp[MAXN][MAXN];
int a[MAXN], len; ll dfs(int pos, int ans, int lead, int limit, int key)
{
if(pos > len) return ans;
if(dp[pos][ans] != - && (!lead && !limit)) return dp[pos][ans];
int l = limit ? a[len-pos+] : ; ll res = ;
_for(i, , l)
{
if(!i && lead) res += dfs(pos + , ans, lead, limit && (i == l), key);
else res += dfs(pos + , ans + (i == key), , limit && (i == l), key);
}
return (!lead && !limit) ? dp[pos][ans] = res : res;
} ll part(ll x, int i)
{
memset(dp, -, sizeof(dp));
len = ;
for(; x > ; x /= ) a[++len] = x % ;
return dfs(, , , , i);
} inline ll work(ll a, ll b, int i)
{
return a ? part(b, i) - part(a - , i) : part(b, i) - part(a, i) + (i == );
} int main()
{
ll a, b;
scanf("%lld%lld", &a, &b);
_for(i, , )
printf("%lld%c", work(a, b, i), i == ? '\n' : ' ');
return ;
}
P3413 SAC#1 - 萌数
注意数字很大,要用字符串存储
然后就没啥了,又独立做出紫题
#include<bits/stdc++.h>
#define add(a, b) a = (a + b) % mod
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; const int MAXN = ;
const int MAXM = 1e3 + ;
const int mod = 1e9 + ; int dp[MAXM][MAXN][MAXN][];
int a[MAXM], len;
char s1[MAXM], s2[MAXM]; int dfs(int pos, int pre, int ppre, int ans, int lead, int limit)
{
if(pos > len) return ans;
if(dp[pos][pre][ppre][ans] != - && (!lead && !limit)) return dp[pos][pre][ppre][ans];
int l = limit ? a[len-pos+] : ; int res = ;
_for(i, , l)
{
if(!i && lead) add(res, dfs(pos + , pre, ppre, ans, lead, limit && (i == l)));
else if(i && lead) add(res, dfs(pos + , i, pre, ans, , limit && (i == l)));
else add(res, dfs(pos + , i, pre, ans | (i == pre) | (i == ppre), , limit && (i == l)));
}
return (!lead && !limit) ? dp[pos][pre][ppre][ans] = res : res;
} int part(char* s)
{
memset(dp, -, sizeof(dp));
len = strlen(s + );
_for(i, , len) a[i] = s[len - i + ] - '';
return dfs(, -, -, , , );
} int judge(char* s)
{
_for(i, , strlen(s + ))
if(s[i] == s[i-] || s[i] == s[i-])
return ;
return ;
} int main()
{
scanf("%s%s", s1 + , s2 + );
if(s1[] == && strlen(s1 + ) == ) printf("%d\n", (part(s2) - part(s1) + mod) % mod);
else printf("%d\n", (part(s2) - part(s1) + mod + judge(s1)) % mod);
return ;
}
P4127 [AHOI2009]同类分布
一开始想的时候当前的数肯定是不能记到答案里的
当然如果知道模数,一直取模就可以限制范围,就很好了
但问题是我们并不知道模数,这就比较尴尬了
就一直卡在这
然而正解非常暴力,但却是对的。
既然不知道模数,那就枚举模数
最后判断一下数字和是不是当前模数且能否整除就好了。
我为什么没想到呢?
注意数位dp要开long long
#include<bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; typedef long long ll;
const int MAXN = ;
ll dp[MAXN][MAXN*][MAXN*];
int a[MAXN], len, mod; ll dfs(int pos, int num, int state, int lead, int limit)
{
if(pos > len) return num == mod && state == ;
if(dp[pos][num][state] != - && (!lead && !limit)) return dp[pos][num][state];
int l = limit ? a[len-pos+] : ; ll res = ;
_for(i, , l)
{
if(!i && lead) res += dfs(pos + , num, state, lead, limit && (i == l));
else if(i && lead) res += dfs(pos + , i, i % mod, , limit && (i == l));
else res += dfs(pos + , num + i, (state * + i) % mod, , limit && (i == l));
}
return (!lead && !limit) ? dp[pos][num][state] = res : res;
} ll part(ll x)
{
len = ;
for(; x; x /= ) a[++len] = x % ;
ll res = ;
for(mod = ; mod <= len * ; mod++)
{
memset(dp, -, sizeof(dp));
res += dfs(, , , , );
}
return res;
} int main()
{
ll a, b;
scanf("%lld%lld", &a, &b);
printf("%lld\n", !a ? part(b) - part(a) : part(b) - part(a - ));
return ;
}
P4317 花神的数论题
用二进制统计就好了
不过很奇怪的是一开始我数组开的大小是50
因为用程序输出1e15最多的位数是47
但是交上去会WA一个点
改成51就过了
以后只要空间剩余多,就多开一些吧,程序中有些神奇的地方可能会比理论上最大值超出一些
#include<bits/stdc++.h>
#define mul(a, b) a = (a * b) % mod
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; typedef long long ll;
const int MAXN = ;
const int mod = ;
ll dp[MAXN][MAXN];
int a[MAXN], len; ll dfs(int pos, int ans, int lead, int limit)
{
if(pos > len) return max(, ans);
if(dp[pos][ans] != - && (!limit && !lead)) return dp[pos][ans];
int l = limit ? a[len-pos+] : ; ll res = ;
_for(i, , l)
{
if(!i && lead) mul(res, dfs(pos + , ans, lead, limit && (i == l)));
else mul(res, dfs(pos + , ans + i, , limit && (i == l)));
}
return (!limit && !lead) ? dp[pos][ans] = res : res;
} ll part(ll x)
{
len = ;
for(; x; x >>= ) a[++len] = x & ;
memset(dp, -, sizeof(dp));
return dfs(, , , );
} int main()
{
ll a;
scanf("%lld", &a);
printf("%lld\n", part(a));
return ;
}
总结
感觉都是套路,掌握套路就好了
相信自己已经掌握了数位dp
数位dp题集的更多相关文章
- (计数器)NOIP模拟赛(神奇的数位DP题。。)
没有原题传送门.. 手打原题QAQ [问题描述] 一本书的页数为N,页码从1开始编起,请你求出全部页码中,用了多少个0,1,2,…,9.其中—个页码不含多余的0,如N=1234时第5页不是00 ...
- 杭电dp题集,附链接还有解题报告!!!!!
Robberies 点击打开链接 背包;第一次做的时候把概率当做背包(放大100000倍化为整数):在此范围内最多能抢多少钱 最脑残的是把总的概率以为是抢N家银行的概率之和- 把状态转移方程写成了f ...
- DP 题集 2
关于 DP 的一些题目 String painter 先区间 DP,\(dp[l][r]\) 表示把一个空串涂成 \(t[l,r]\) 这个子串的最小花费.再考虑 \(s\) 字符串,\(f[i]\) ...
- DP 题集 1
关于 DP 的一些题目 参考资料 [Tutorial] Non-trivial DP Tricks and Techniques DP Rain and Umbrellas Mr. Kitayuta, ...
- 浅谈数位DP
在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...
- HDU 3709 Balanced Number (数位DP)
Balanced Number Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) ...
- 数位DP之小小结
资料链接:http://wenku.baidu.com/view/9de41d51168884868662d623.html http://wenku.baidu.com/view/d2414ffe0 ...
- HDU5787 K-wolf Number 数位dp
分析:赛场上也知道是裸的数位dp,但是无奈刷数位dp题刷的太少了,并不能写出来 一点感想:赛后补题,看了题解的map记录状态,一脸蒙逼,也是非常的不爽,然后想看别人写的,不是递归就是写的比较乱 而且我 ...
- ural 1057(数位dp)
数位dp题,关键是用树的思维去考虑. 对于一个数字X,要是能表示成K个B的不同次幂,等价于X在B进制下有且只有K个位上面的数字为一,其他位上的数字都为0. 具体读者可以去参考,国家集训队李聪的论文,里 ...
随机推荐
- 很强大的shell写的俄罗斯方块
网上看到的一个用linux的shell脚本写的俄罗斯方块. 是我至今见过写的最牛逼的shell了.共享一下. 原作者信息在脚本的凝视中有. 下载地址:点击下载 #!/bin/bash # Tetris ...
- Codeforces Round #250 Div. 2(C.The Child and Toy)
题目例如以下: C. The Child and Toy time limit per test 1 second memory limit per test 256 megabytes input ...
- splunk的bucket组织目录——时间序列,按照时间来组织目录
splunk的bucket组织目录:db_1481515116_1480695302_0db_1481537316_1481532688_1db_1481547598_1481539988_2db_1 ...
- P2532 [AHOI2012]树屋阶梯 卡特兰数
这个题是一个卡特兰数的裸题,为什么呢?因为可以通过划分来导出递推式从而判断是卡特兰数,然后直接上公式就行了.卡特兰数的公式见链接. https://www.luogu.org/problemnew/s ...
- ecshop数据库说明
数据库 ecshop 表的结构 ecs_account_log 字段 类型 空 默认 含义 log_id mediumint(8) 否 账户记录表 user_id mediumint(8) 否 用户编 ...
- Mysql数据库系列
详情点击 MySQL基础 Mysql表操作 Mysql插入 更新 删除 查询操作 Mysql创建用户和授权 基本的Mysql语句 Mysql库的操作 Mysql表的操作 Mysql数据类型(一) My ...
- # --with-http_sub_module模块
作用: http内容替换 语法 第一种语法: sub_filter string:要替换的内容 替换后的内容 这个模块只能替换第一个匹配的字符串,如果需要匹配全部替换,则用到下面的第三种语法配置 第二 ...
- 实现Brush对象的五种图形
本实例将使用Graphics类绘制五种图形来分别演示SolidBrush.HatchBrush.TextureBrush.LinearGradientBrush.PathGradientBrush这五 ...
- Assembly之Instruction之Byte and Word
Byte and word issues The MSP430 is byte-addressed, and little-endian. Word operands must be located ...
- iOS-如何返回某个字符串的拼音助记码
我也是看了网上的一个示例代码后,在它的基础上进行的修改.因为项目上会用到,我相信很多人的项目上也会用到.所以实现后,也赶紧分享出来,希望后来人不需要花费时间了. 提示:这里用到了正则表达式,使用了一个 ...