数位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. 具体读者可以去参考,国家集训队李聪的论文,里 ...
随机推荐
- Android push推送消息到达成功率优化
Android push推送消息到达成功率优化 问题:server向client发送消息.未考虑client是否在线,这种消息到达率是非常低的. 第一次优化:使用server离线缓存数据,推断假设cl ...
- crm使用FetchXml分组聚合查询
/* 创建者:菜刀居士的博客 * 创建日期:2014年07月09号 */ namespace Net.CRM.FetchXml { using System; using Micr ...
- WPF学习笔记——DataContext 与 ItemSource
作为一个WPF新手,在ListBox控件里,我分不清 DataContext 与 ItemSource的区别. 在实践中,似乎: <ListBox x:Name="Lst" ...
- luogu2024 食物链
题目大意 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B吃 C,C 吃 A.现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我们并 ...
- elasticsearch 索引搜索和索引性能优化配置——思路:去掉不必要的数据,减小数据的磁盘空间占用,同时提升性能
压缩配置: index.codec: best_compression 合并索引: curl –XPOST localhost:9200/hec_test3/_forcemerge’ 配置mappin ...
- Codeforces Round #402 D(二分)
D. String Game ...
- B2460 [BeiJing2011]元素 线性基
这个题是对刚才线性基的一个补充,就是中间有一些小贪心,贪心就很有意思,先按权值排序,然后就瞎搞就行了. 题干: Description 相传,在远古时期,位于西方大陆的 Magic Land 上,人们 ...
- iOS手势识别
一.手势识别与触摸事件 1.如果想监听一个view上面的触摸事件,可选的做法是: (1)自定义一个view (2)实现view的touches方法,在方法内部实现具体处理代码 2.通过touches方 ...
- 3个不常用的HTML标签
html标签众多,在HTML手册里你可以都查到.但有的HTML标签你可能从未使用过.不是因为你欠缺学习精神,而是它们确实用处不大.如果你有探索精神,那就接着往下看吧. 第一个:<abbr> ...
- Windows<小白>详细笔记
Windows 7 部署 =========================================== ========================================== ...