题意

将1~N(1<=N<=10^15)写在纸上,然后在相邻的数字间交替插入+和-,求最后的结果。例如当N为12时,答案为:+1-2+3-4+5-6+7-8+9-1+0-1+1-1+2=5。

思路

花了一上午时间调BUG……必须承认SPOJ上的好题很多~每次做都有很大收获…… 我发现原来记忆化搜索的数位DP不止可以做统计,还可以做计算。我们应该把记忆化搜索形式的数位DP理解成一种处理与各位数字有关问题的一种方法,或者也可以延伸到字符串上。 我们可以把数列在纸上写一下:

-0
+1
-2
+3
-4
+5
……
-8
+9-1+0
-1+1
……
-1+9
-2+0
-2+1
……
-9+9-1+0-0
+1-0+1
-1+0-2
……
+1-9+9
-2+0-0
…………

可以发现:如果数位为偶数,那么对应位的符号都一样,并且第一个符号为负,交替改变;如果数位为奇数,那么每一位符号都是交错的,可以两两抵消,只需计算个位即可。 然后状态设计就好说了:pos、limit这些基本参数不用说。还需要一个pre记录上一位,以便数位为奇数时计算最后一位;一个sum表示各位数符号交替之和,用于数位为偶数时的计算;一个sub表示当前数位的符号(+/-);一个state表示数位是奇数还是偶数。 这里就需要注意最重要的一点:设计dp[][]状态时一定要使得每一个dp数组都唯一且明确对应一个区间,这样才可以只在程序开始时初始化dp数组,否则就需要在每次询问[1,N]区间前都初始化!什么意思?比如一开始时,我们会把N拆成数位存起来,而我的state表示的是当前枚举的数从左数第一个非零位的位置(即数的起始位置),以此来判断最后数位的奇偶性。那这样的state就很不明确了,因为他的意义会随着N的数位的变动而变化,我们当然可以增加一维数组表示当前N的位数,但那样就绕远了,而且空间不允许。所以我修正了state的含义:state=0表示当前奇偶不确定,即前面枚举的数位全都是0;state=1表示当前数位为奇数;state=2表示偶数。这个在第一次i!=0时就可以更新状态,详细看代码吧~

代码

[cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m) for (int i = begin; i < begin+m; i ++) using namespace std; typedef long long LL; typedef vector VI; typedef set SETI; typedef queue QI; typedef stack SI; const int oo = 0x3fffffff; VI num; LL dp[16][10][280][3][2]; LL dfs(int pos, int pre, int sum, int state, bool sub, bool limit){ if (pos == -1){ if (state == 1) return (pre&1)?pre:-pre; else return sum; } if (!limit && ~dp[pos][pre][sum+140][state][sub]) return dp[pos][pre][sum+140][state][sub]; int end = limit?num[pos]:9; LL res = 0; for (int i = 0; i <= end; i ++){ bool st = !state && (i == 0); int next_state = state; if (!state && i > 0){ if ((pos+1)%2==0) next_state = 2; else next_state = 1; } res += dfs(pos-1, i, sub?sum-i:sum+i, next_state, st?true:sub^1, limit&&(i==end)); } return limit?res:dp[pos][pre][sum+140][state][sub]=res; } LL cal(LL x){ num.clear(); LL res = 0; if (x % 2 == 0){ LL tmp = x; while(tmp){ num.push_back(tmp%10); tmp /= 10; } for (int i = (int)num.size()-1, k = -1; i >= 0; i --, k*=-1){ res += num[i]*k; } x --; } num.clear(); while(x){ num.push_back(x%10); x /= 10; } int len = (int)num.size(); return res + dfs(len-1, 0, 0, 0, true, true); } int main(){ LL n; MEM(dp, -1); while(~scanf("%lld", &n)){ if (n == 0) break; printf("%lld\n", cal(n)); } return 0; } [/cpp]

转载于:https://www.cnblogs.com/AbandonZHANG/p/4114101.html

SPOJ KPSUM ★(数位DP)相关推荐

  1. SPOJ MYQ10 (数位DP)

    题意 询问区间[a,b]中的Mirror Number的个数,其中Mirror Number是指把它横着翻转后还能表示同样的数字. 思路 注意这个可不是回文数..除了0,1,8,别的数字翻转过后就不是 ...

  2. SPOJ 10606 数位DP

    SPOJ-10606 solution 坑点在于前导零对于统计 000 的个数的影响. dp[pos][num][appear]dp[pos][num][appear]dp[pos][num][app ...

  3. [SPOJ IGAME Interesting Game]Nim 博弈+数位DP

    [SPOJ IGAME Interesting Game]Nim 博弈+数位DP 分类:博弈 数位DP 1. 题目链接 [SPOJ IGAME Interesting Game] 2. 题意描述 Al ...

  4. [数位dp] spoj 10738 Ra-One Numbers

    题意:给定x.y.为[x,y]之间有多少个数的偶数位和减去奇数位和等于一. 个位是第一位. 样例: 10=1-0=1 所以10是这种数 思路:数位dp[i][sum][ok] i位和为sum 是否含有 ...

  5. SPOJ - BALNUM Balanced Numbers(数位dp+进制转换)

    题目链接:点击查看 题目大意:给出平衡数的定义:每一个偶数出现的次数必须是奇数次,每一个奇数出现的次数必须是偶数次,求给定区间中有多少个平衡数 题目分析:数位dp,这个题目就难在怎么确定状态转移,本来 ...

  6. 【bzoj 1833】【codevs 1359】 [ZJOI2010]count 数字计数(数位dp)

    1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MB Submit: 2774  Solved: 1230 [Submit ...

  7. 不要62 ---数位DP

    题意:求m到n中不含62和4的数的个数. 题目链接 思路:数位dp模板求满足的数字或不满足的数字,刚学,就求不满足的数. #include<stdio.h> #include<str ...

  8. bzoj 3598 [ Scoi 2014 ] 方伯伯的商场之旅 ——数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3598 数位DP...东看西看:http://www.cnblogs.com/Artanis/ ...

  9. cojs 简单的数位DP 题解报告

    首先这道题真的是个数位DP 我们考虑所有的限制: 首先第六个限制和第二个限制是重复的,保留第二个限制即可 第五个限制在转移中可以判断,不用放在状态里 对于第一个限制,我们可以增加一维表示余数即可 对于 ...

最新文章

  1. SpringMVC-applicationContent.xml和Spring-servlet.xml的配置设置
  2. STM32-I2C总线驱动程序分析
  3. 写一个能自动生成四则运算题目的软件,要求除了整数,还要支持正分数的四则运算。和同学们比较各自的程序功能、实现方法的异同。...
  4. [java]apache server与 tomcat 的区别以及整合
  5. java怎么缓存行填充_为什么java的Exchanger.Slot缓存行填充像这样?
  6. 函数的返回值-改造求和函数
  7. js滚动条下拉一定值_JS逆向 | 无限Debugger之淘大象
  8. 最详细的R-CNN论文笔记
  9. andorid 回调的理解
  10. p12解析流程_iOS证书及描述文件制作流程详解
  11. 【数据库原理实验(openGauss)】 安全性控制
  12. BZOJ 2339 【HNOI2011】 卡农
  13. oracle 2703,Oracle11gR2光钎链路切换crs服务发生crash
  14. 三大强者效应:鲶鱼效应,鳄鱼效应,鲦鱼效应
  15. 品牌出海:如何做好本土化运营?
  16. windows下使用控制台打开conda虚拟环境
  17. win10安装MySQL常见问题_win10 安装MySQL过程和遇到的坑
  18. non-resource variables are not supported in the long term 无法解决
  19. leetcode 巧妙解法 387. 字符串中的第一个唯一字符
  20. 基于Java+数据爬虫+SSM架构实现手机购物网站前后台项目

热门文章

  1. 如何鉴别项目经理/软件设计师的水平
  2. 开源GIS(三)——openlayers地图基本框架与天地图加载
  3. 你最喜欢哪款游戏的界面风格,为什么?
  4. table多行表头合并 vue_vue elementUI table 自定义表头和行合并的实例代码
  5. 【java学习之路】(java框架)006.springIOC
  6. android 多类型参数,Android的数据绑定-类型参数T具有不兼容的上限:ViewDataBinding和MainActivity...
  7. Impala与Hive的关系
  8. 查看CDH平台各个组件的版本
  9. html 图片 按钮,css按钮背景图片如何实现?(代码实例)
  10. scala函数式编程