数位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. 具体读者可以去参考,国家集训队李聪的论文,里 ...
随机推荐
- spring mvc文件上传,request对象转换异常
spring 文件上传有现成的工具用起来也挺简单.就是在还不是非常熟悉的时候可能会出一些错. 近期碰到了 org.apache.catalina.connector.RequestFacade can ...
- 使用playonlinux安装windows软件
转载 http://qspy.is-programmer.com/posts/40913.html Wine提供了一个用来运行Windows程序的平台.PlayOnLinux 是使用 Python 写 ...
- 73. 解决ExtJS TreePanel 的 iconCls设置问题
转自:https://blog.csdn.net/hanchuang213/article/details/62881568 很久没有写代码了,最近在做一个在线帮助网站,于是又捡起了 ExtJS,我用 ...
- 第7章 Android中访问网络资源
http://developer.android.com/index.html->https://developer.android.com/index.html https://develop ...
- hdu4405Aeroplane chess(概率与期望dp)
Aeroplane chess Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- css3 选择器 权重问题 (第一部分)
其实我现在写的这些博文笔记都是我很早之前学习的时候所写的笔记,只不过之前是没有写博客的习惯,所以都是写在word文档中个人需要的时候看而已.最近刚刚开了博客,所以想将自己的笔记贴到博客. 但是现在看来 ...
- 【STM32H7教程】第23章 STM32H7的MPU内存保护单元(重要)
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第23章 STM32H7的MPU内存保护单元 ...
- android开发 设备调试问题
如果在mac下面用趁机开发android程序,发现不能连接上时就需要进行简单设置即可 先设置Finder为可以显示所有隐藏文件夹: 打开终端,输入如下命令: 显示Mac隐藏文件的命令:defaults ...
- Hibernate多表查询、查询优化策略(四)
多表HQL private static void innerJoin(){ //sql内连接 隐式内连接 select * from A,B where b.aid = a.id // 显示内连接 ...
- 《CSS Mastery》读书笔记(4)
第七章 布局 CSS得到一个不好的名声,比较难懂, 一方面由于浏览器的不兼容,另一方面由于网上大量的技巧,每个CSS作者都可以有自己的方法去创建多列布局, 新的CSS开发者只是使用一种方法而不去理 ...