一、引例

#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。

  1. /*
  2. ************************************交错和***********************************************
  3. ******************************by JA/C++ 2015-1-19****************************************
  4. */
  5.  
  6. #include <cstdio>
  7. #include <cstring>
  8. long long mod = ;
  9. long long base[];
  10. long long l, r, k, bit[], bt, yy;
  11. struct node {
  12. long long s, n;//s代表数字和,n代表数字个数
  13. };
  14. node dp[][];//状态转移
  15. node dfs(long long pos, long long target, long long limit)//数位dp,基本可以算是模板啦
  16. {
  17. node t;
  18. t.s = t.n = ;
  19. if (pos == ) { //处理到最后一位,直接判断返回
  20. if (target == )
  21. t.n = ;
  22. return t;
  23. }
  24. if ((limit == ) && (dp[pos][target].n != -)) return dp[pos][target];
  25. long long tail = limit ? bit[pos] : ;
  26. long long sgn = ((yy - pos) % ) ? (-) : ();//确定符号
  27. long long head;
  28. if (pos == yy)head = ;
  29. else head = ;//确定搜索的起点和终点
  30. for (long long i= head; i <= tail; i++)
  31. {
  32. node tmp = dfs(pos - , target - i*sgn, (limit == ) && (i == bit[pos]));
  33. if ((tmp.n)>){
  34. t.n += tmp.n;
  35. long long q;
  36. q = ((((tmp.n%mod)*base[pos]) % mod)*i) % mod;//结果的同余处理
  37. t.s += (tmp.s) % mod;
  38. t.s %= mod;
  39. t.s += q;
  40. t.s %= mod;//每一步都要同余
  41. }
  42. }
  43. if (limit == ) dp[pos][target] = t;
  44. return t;
  45. }
  46. long long cal(long long x, long long y)
  47. {
  48. long long ans = ;
  49. if (x == -) return ;
  50. if (x == ) return ;
  51. bt = ;
  52. while (x)
  53. {
  54. bt++;
  55. bit[bt] = x % ;
  56. x /= ;
  57. }
  58. for (yy = ; yy <= bt; yy++){
  59. memset(dp, -, sizeof dp);
  60. ans += dfs(yy, y + , yy == bt).s;//对于每个长度为yy的数字进行处理
  61. ans = (ans + mod) % mod;
  62. }
  63. return ans;
  64. }
  65. int main()
  66. {
  67. base[] = ;
  68. for (int i = ; i <= ; i++)
  69. base[i] = (base[i - ] * ) % mod;
  70. scanf("%lld%lld%lld", &l, &r, &k);
  71. //scanf_s("%lld%lld%lld", &l, &r, &k);
  72. {
  73. printf("%lld", (cal(r, k) - cal(l - , k) + mod) % mod);
  74. }
  75. return ;
  76. }

二、思路分析

给定取值范围,要求区间内数的交错和为给定数,需要用到数位dp,记忆搜索以及同余定理

1.记忆化搜索写的时候要将相同交错和的个数,相同交错和的数字和分别进行dp。

2.对于一位数字和两位数字的计算方式并不相同,要分数字的位数进行讨论。

3.由于结果可能比较大,每一步都需要使用同余定理。

三、数位dp模板

  1. const int MAX_DIGITS, MAX_STATUS;
  2. LL f[MAX_DIGITS][MAX_STATUS], bits[MAX_DIGITS];
  3.  
  4. LL dfs(int position, int status, bool limit, bool first)
  5. {
  6. if (position == -)
  7. return s == target_status;
  8. if (!limit && !first && ~f[position][status])
  9. return f[position][status];
  10. int u = limit ? bits[position] : MAX_BITS;
  11. LL ret = ;
  12. for (int i = ; i <= u; i++)
  13. {
  14. ret += dfs(position - , next_status(status, i), limit && i == u, first && !i);
  15. }
  16. return limit || first ? ret : f[pos][status] = ret;
  17. }
  18.  
  19. LL calc(LL n)
  20. {
  21. CLR(f, -);
  22. int len = ;
  23. while (n)
  24. {
  25. bits[len++] = n % ;
  26. n /= ;
  27. }
  28. return dfs(len - , , true, true);
  29. }
  30.  
  31. int main()
  32. {
  33. //freopen("0.txt", "r", stdin);
  34. LL a, b;
  35. while (cin >> a >> b)
  36. cout << calc(b) - calc(a - ) << endl;
  37. return ;
  38. }

四、记忆化搜索

记忆化搜索=搜索的形式+动态规划的思想

参考文献

1.算法合集之《浅谈数位类统计问题》——刘聪

2.推酷《数位dp模板

数位dp/记忆化搜索的更多相关文章

  1. [hihocoder 1033]交错和 数位dp/记忆化搜索

    #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1 ...

  2. 【poj1850】 Code 数位dp+记忆化搜索

    题目大意:给你一个字符串,问你这个字符串的rank,如果这个字符串不合法,请直接输出0.(一个合法的字符串是对于∀i,有c[i]<c[i+1]) 字符串s的rank的计算方式:以字符串长度作为第 ...

  3. [BZOJ3598][SCOI2014]方伯伯的商场之旅(数位DP,记忆化搜索)

    3598: [Scoi2014]方伯伯的商场之旅 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 449  Solved: 254[Submit][Sta ...

  4. bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)

    1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...

  5. 1026-windy数+数位DP+记忆化搜索

    1026: [SCOI2009]windy数 题意:数位DP模板题: 目前只理解了记忆化搜索,就想练练手, ------给递推写法留一个位子 ------ 注意这道题要判断前导0的情况,1 )可以加一 ...

  6. 【每日dp】 Gym - 101889E Enigma 数位dp 记忆化搜索

    题意:给你一个长度为1000的串以及一个数n 让你将串中的‘?’填上数字 使得该串是n的倍数而且最小(没有前导零) 题解:dp,令dp[len][mod]为是否出现过 填到第len位,余数为mod 的 ...

  7. luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索

    题目链接 luogu P2657 [SCOI2009]windy数 题解 我有了一种所有数位dp都能用记忆话搜索水的错觉 代码 #include<cstdio> #include<a ...

  8. hdu3652 数位dp记忆化搜索

    从未见过的船新版本数位dp,,省去了预处理过程,直接进行计算 #include<bits/stdc++.h> using namespace std; #define ll long lo ...

  9. cf55D 数位dp记忆化搜索+状态离散

    /* 漂亮数定义:可以整除任意数位上的数 求出区间[l,r]之间的漂亮数个数 因为 dp[i][j][k]:i位前模lcm的值是j,i位前lcm是k的漂亮数个数 */ #include<bits ...

随机推荐

  1. 泛型容器单元(Generics.Collections)[3]: TStack<T> 堆栈列表

    TQueue 和 TStack, 一个是队列列表, 一个是堆栈列表; 一个是先进先出, 一个是先进后出. TStack 主要有三个方法.一个属性:Push(压栈).Pop(出栈).Peek(查看下一个 ...

  2. eclipse 异常Unhandled event loop exception解决办法

    http://blog.csdn.net/leiswpu/article/details/26712709

  3. Android App 性能优化实践

    本文记录了Android App优化需要用到的工具和以及在实践中的Tips.也算对我这半年来部分工作的总结. 工具 Hierarchy Viewer 是 Android SDK 自带的 Layout ...

  4. PHP、Java对称加密中的AES加密方法

    PHP AES加密 <?php ini_set('default_charset','utf-8'); class AES{ public $iv = null; public $key = n ...

  5. Python 学习笔记01

      print:直接输出 type,求类型 数据类型:字符串,整型,浮点型,Bool型     note01.py # python learning note 01   print('Hello w ...

  6. three.js透视投影照相机

    透视投影照相机(Perspective Camera)的构造函数是: THREE.PerspectiveCamera(fov, aspect, near, far) 让我们通过一张透视照相机投影的图来 ...

  7. 编程之路 - 写给打算进入IT行业的新人们

    IT=挨踢,这是IT人的自嘲,进入IT行业是有四五年了,也算得上是一个“老人”了吧,见了不少新人,面试了不少新人,也带了一些新人,多多少少还是有点发言权的. 关于书本 新人们常常会说我看了多少多少的书 ...

  8. BZOJ4662 : Snow

    首先离散化,即相邻关键点之间的部分可以压成一段. 注意到区间互不包含,因此排序后每个位置的清理影响到的是一段连续区间的清理工的工作长度. 这显然可以用线段树维护,支持区间减去一个数,单点加上$inf$ ...

  9. PE-2 & 暴模...

    题意: 求不大于4000000的斐波那契数列中,所有偶数之和. SOL: 还是只会暴模...看讨论区貌似有一个很牛逼的大神的发言? 英语水平太差... mark以下 The Fibonacci seq ...

  10. CUDA程序设计(三)

    算法设计:基数排序 CUDA程序里应当尽量避免递归,因而在迭代排序算法里,基数排序通常作为首选. 1.1 串行算法实现 十进制位的基数排序需要考虑数位对齐问题,比较麻烦.通常实现的是二进制位的基数排序 ...