数位dp/记忆化搜索
一、引例
#1033 : 交错和
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数:
f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1
例如:
f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4
给定 l, r, k,求在 [l, r] 区间中,所有 f(x) = k 的 x 的和,即:
1405402477702.png
输入
输入数据仅一行包含三个整数,l, r, k(0 ≤ l ≤ r ≤ 1018, |k| ≤ 100)。
输出
输出一行一个整数表示结果,考虑到答案可能很大,输出结果模 109 + 7。
提示
对于样例 ,满足条件的数有 110 和 121,所以结果是 231 = 110 + 121。
/*
************************************交错和***********************************************
******************************by JA/C++ 2015-1-19****************************************
*/ #include <cstdio>
#include <cstring>
long long mod = ;
long long base[];
long long l, r, k, bit[], bt, yy;
struct node {
long long s, n;//s代表数字和,n代表数字个数
};
node dp[][];//状态转移
node dfs(long long pos, long long target, long long limit)//数位dp,基本可以算是模板啦
{
node t;
t.s = t.n = ;
if (pos == ) { //处理到最后一位,直接判断返回
if (target == )
t.n = ;
return t;
}
if ((limit == ) && (dp[pos][target].n != -)) return dp[pos][target];
long long tail = limit ? bit[pos] : ;
long long sgn = ((yy - pos) % ) ? (-) : ();//确定符号
long long head;
if (pos == yy)head = ;
else head = ;//确定搜索的起点和终点
for (long long i= head; i <= tail; i++)
{
node tmp = dfs(pos - , target - i*sgn, (limit == ) && (i == bit[pos]));
if ((tmp.n)>){
t.n += tmp.n;
long long q;
q = ((((tmp.n%mod)*base[pos]) % mod)*i) % mod;//结果的同余处理
t.s += (tmp.s) % mod;
t.s %= mod;
t.s += q;
t.s %= mod;//每一步都要同余
}
}
if (limit == ) dp[pos][target] = t;
return t;
}
long long cal(long long x, long long y)
{
long long ans = ;
if (x == -) return ;
if (x == ) return ;
bt = ;
while (x)
{
bt++;
bit[bt] = x % ;
x /= ;
}
for (yy = ; yy <= bt; yy++){
memset(dp, -, sizeof dp);
ans += dfs(yy, y + , yy == bt).s;//对于每个长度为yy的数字进行处理
ans = (ans + mod) % mod;
}
return ans;
}
int main()
{
base[] = ;
for (int i = ; i <= ; i++)
base[i] = (base[i - ] * ) % mod;
scanf("%lld%lld%lld", &l, &r, &k);
//scanf_s("%lld%lld%lld", &l, &r, &k);
{
printf("%lld", (cal(r, k) - cal(l - , k) + mod) % mod);
}
return ;
}
二、思路分析
给定取值范围,要求区间内数的交错和为给定数,需要用到数位dp,记忆搜索以及同余定理。
1.记忆化搜索写的时候要将相同交错和的个数,相同交错和的数字和分别进行dp。
2.对于一位数字和两位数字的计算方式并不相同,要分数字的位数进行讨论。
3.由于结果可能比较大,每一步都需要使用同余定理。
三、数位dp模板
const int MAX_DIGITS, MAX_STATUS;
LL f[MAX_DIGITS][MAX_STATUS], bits[MAX_DIGITS]; LL dfs(int position, int status, bool limit, bool first)
{
if (position == -)
return s == target_status;
if (!limit && !first && ~f[position][status])
return f[position][status];
int u = limit ? bits[position] : MAX_BITS;
LL ret = ;
for (int i = ; i <= u; i++)
{
ret += dfs(position - , next_status(status, i), limit && i == u, first && !i);
}
return limit || first ? ret : f[pos][status] = ret;
} LL calc(LL n)
{
CLR(f, -);
int len = ;
while (n)
{
bits[len++] = n % ;
n /= ;
}
return dfs(len - , , true, true);
} int main()
{
//freopen("0.txt", "r", stdin);
LL a, b;
while (cin >> a >> b)
cout << calc(b) - calc(a - ) << endl;
return ;
}
四、记忆化搜索
记忆化搜索=搜索的形式+动态规划的思想
参考文献
1.算法合集之《浅谈数位类统计问题》——刘聪
2.推酷《数位dp模板》
数位dp/记忆化搜索的更多相关文章
- [hihocoder 1033]交错和 数位dp/记忆化搜索
#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1 ...
- 【poj1850】 Code 数位dp+记忆化搜索
题目大意:给你一个字符串,问你这个字符串的rank,如果这个字符串不合法,请直接输出0.(一个合法的字符串是对于∀i,有c[i]<c[i+1]) 字符串s的rank的计算方式:以字符串长度作为第 ...
- [BZOJ3598][SCOI2014]方伯伯的商场之旅(数位DP,记忆化搜索)
3598: [Scoi2014]方伯伯的商场之旅 Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 449 Solved: 254[Submit][Sta ...
- bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)
1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...
- 1026-windy数+数位DP+记忆化搜索
1026: [SCOI2009]windy数 题意:数位DP模板题: 目前只理解了记忆化搜索,就想练练手, ------给递推写法留一个位子 ------ 注意这道题要判断前导0的情况,1 )可以加一 ...
- 【每日dp】 Gym - 101889E Enigma 数位dp 记忆化搜索
题意:给你一个长度为1000的串以及一个数n 让你将串中的‘?’填上数字 使得该串是n的倍数而且最小(没有前导零) 题解:dp,令dp[len][mod]为是否出现过 填到第len位,余数为mod 的 ...
- luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索
题目链接 luogu P2657 [SCOI2009]windy数 题解 我有了一种所有数位dp都能用记忆话搜索水的错觉 代码 #include<cstdio> #include<a ...
- hdu3652 数位dp记忆化搜索
从未见过的船新版本数位dp,,省去了预处理过程,直接进行计算 #include<bits/stdc++.h> using namespace std; #define ll long lo ...
- cf55D 数位dp记忆化搜索+状态离散
/* 漂亮数定义:可以整除任意数位上的数 求出区间[l,r]之间的漂亮数个数 因为 dp[i][j][k]:i位前模lcm的值是j,i位前lcm是k的漂亮数个数 */ #include<bits ...
随机推荐
- 利用K-means聚类分类,进行特征学习
这只是老师安排的一个实验,准备过程中遇到各种问题,现在贴出来供大家参考,是Andrew Ng参与的研究, 论文依据如下,第二篇是一篇相关的论文, Learning Feature Representa ...
- OpenCV(5) 对比度和亮度
公式: 两个参数 \alpha > 0 和 \beta 一般称作 增益 和 偏置 参数.我们往往用这两个参数来分别控制 对比度 和 亮度 . #include "stdafx. ...
- webvnc利器-noVNC集成实战
我们在做一个虚拟机管理平台,底层虚拟化使用KVM,我们希望在网页上操作虚拟机. 一开始用applet嵌在网页内实现webvnc,不过由于applet的在浏览器上运行安全性限制,我们需要一个新的方案.此 ...
- POJ1904 King's Quest(完备匹配可行边:强连通分量)
题目大概就是说给一张二分图以及它的一个完备匹配,现在问X部的各个点可以与Y部那些些点匹配,使得X部其余点都能找到完备匹配. 枚举然后匹配,当然不行,会超时. 这题的解法是,在二分图基础上建一个有向图: ...
- POJ3368 Frequent values(RMQ线段树)
题目大概说给一个递增序列,询问区间出现最多的数. 用莫队算法比较直观,虽然应该会T..好像也可以主席树..不过题目给的序列是有序的,因而相同的数会聚在一起. 考虑把序列分成一段一段,使每段都包含极大的 ...
- The 2015 China Collegiate Programming Contest L. Huatuo's Medicine hdu 5551
Huatuo's Medicine Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others ...
- iOS学习01C语言数据类型
1.注释 // 单行注释 // 注释对代码起到解释说明的作用,注释是给程序员看的,不参与程序运行 /* 多行注释 Xcode快捷键 全选 cmd+a 复制 cmd+c 粘贴 cmd+v 设 ...
- Start_Learning_Python 03 条件、循环
if循环 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 条件语句和循环语句可以有 else 子句,它在穷尽列表(以for循环)或条件变为 false ...
- 如何终止java线程
http://blog.csdn.net/anhuidelinger/article/details/11746365 终止线程的三种方法 有三种方法可以使终止线程. 1. 使用退出标志,使线程正常 ...
- 【BZOJ】1406: [AHOI2007]密码箱
http://www.lydsy.com/JudgeOnline/problem.php?id=1406 题意:求$0<=x<n, 1<=n<=2,000,000,000, 且 ...