【BZOJ1236】KPSUM,记数类问题(乱搞)
2016-03-28 15:13
357 查看
传送门
权限题,放一下题面
1236: SPOJ1433 KPSUM
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 163 Solved: 87
[Submit][Status][Discuss]
Description
给你一个正整数N,依次把1到N写下来,在每两个数字之间交替的加上+,-号(注意是数字不是数),求这个表达式的值。例如,N=15时,表达式为1-2+3-4+5-6+7-8+9-1+0-1+1-1+2-1+3-1+4-1+5
Input
一个正整数N。
Output
表达式的值。
Sample Input
15
Sample Output
14
数据范围:30%的数据中,N<=100。
100%的数据中,N<=10^15
写在前面:听Shallwe说,这是一篇论文的练习题= =
思路:(调了好久才A,为zky学长的号+AC尽一份力)
第一反应是打表找规律,但是发现这规律并不是那么直接明显,我们进一步分析发现,计算奇数位的数时,相邻的两个数和为1(-2+3,-1+0-0+1-0+1),所以可以直接算出来(即5,450,45000…)。为了方便,我们称形同(2,3)(100,101)的两个数为“数对”。计算偶数位时,很显然每一位前面的运算符是固定的,都是-..+..-..+..,个位、百位……前都是+,十位、千位……前都是-,所以我们可以类似递推得预处理一下,f[i][j]指第i位最大为j时的总和(直接点说,就是0-j999……9,j是第i位),但是都是偶数位的情况下,可能有点难理解,
举个例子说f[1][9]=0+1+2+3+4+5+6+7+8+9
f[2][1]=-1+0-1+1-1+2-1+3-1+4-1+5-1+6-1+7-1+8-1+9,
显然转移时就是
f[i][j]=f[i−1][9](j=0)
f[i][j]=f[i][j−1]+f[i−1][9]+j∗10i−1(i为奇数)
f[i][j]=f[i][j−1]+f[i−1][9]−j∗10i−1(i为偶数)
转移出来后就比较好处理了,这里我们分别以120和2456作为讨论
对120来说,我们可以分块计算0-9和10-99,0-9是奇数位数,直接ans+=5(显然,奇数位时答案直接加5,450,45000……),10-99为偶数位数,我们要ans+=f[2][9],但是f[2][9]里包含了f[2][0],即十位数最高为2的情况包含了十位为0的情况,但是我们的计算是从10开始的,所以要减去f[2][0]
对于100-120,它是奇数位数,所以利用之前得到的性质,计算100-120之间有多少个“数对”,显然这一段对答案的贡献为(120-1-100)/2-1+2-0(最后的120是孤立的,单独计算即可)
对2456来说,形同上计算0-9,10-99,100-999,最后计算1000-2456,这是偶数位数,我们可以继续把它分解成1000-1999(即f[4][1]-f[4][0]),2000-2399(即f[3][3]-2*400),2400-2449(即f[2][4]-2*50+4*50)最后计算时要在个位特判一下,普遍规律就是可以记录一下前边的数数字按位计算的和差×10的几次方×当前位数字(这里有些口胡,因为不是很(想+会)用式子表达)
注意:
还是补充一下个位特判好了,例如计算2400时,在十位的0是不计算的,但个位的0也是一次计算,所以要计算
代码:
权限题,放一下题面
1236: SPOJ1433 KPSUM
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 163 Solved: 87
[Submit][Status][Discuss]
Description
给你一个正整数N,依次把1到N写下来,在每两个数字之间交替的加上+,-号(注意是数字不是数),求这个表达式的值。例如,N=15时,表达式为1-2+3-4+5-6+7-8+9-1+0-1+1-1+2-1+3-1+4-1+5
Input
一个正整数N。
Output
表达式的值。
Sample Input
15
Sample Output
14
数据范围:30%的数据中,N<=100。
100%的数据中,N<=10^15
写在前面:听Shallwe说,这是一篇论文的练习题= =
思路:(调了好久才A,为zky学长的号+AC尽一份力)
第一反应是打表找规律,但是发现这规律并不是那么直接明显,我们进一步分析发现,计算奇数位的数时,相邻的两个数和为1(-2+3,-1+0-0+1-0+1),所以可以直接算出来(即5,450,45000…)。为了方便,我们称形同(2,3)(100,101)的两个数为“数对”。计算偶数位时,很显然每一位前面的运算符是固定的,都是-..+..-..+..,个位、百位……前都是+,十位、千位……前都是-,所以我们可以类似递推得预处理一下,f[i][j]指第i位最大为j时的总和(直接点说,就是0-j999……9,j是第i位),但是都是偶数位的情况下,可能有点难理解,
举个例子说f[1][9]=0+1+2+3+4+5+6+7+8+9
f[2][1]=-1+0-1+1-1+2-1+3-1+4-1+5-1+6-1+7-1+8-1+9,
显然转移时就是
f[i][j]=f[i−1][9](j=0)
f[i][j]=f[i][j−1]+f[i−1][9]+j∗10i−1(i为奇数)
f[i][j]=f[i][j−1]+f[i−1][9]−j∗10i−1(i为偶数)
转移出来后就比较好处理了,这里我们分别以120和2456作为讨论
对120来说,我们可以分块计算0-9和10-99,0-9是奇数位数,直接ans+=5(显然,奇数位时答案直接加5,450,45000……),10-99为偶数位数,我们要ans+=f[2][9],但是f[2][9]里包含了f[2][0],即十位数最高为2的情况包含了十位为0的情况,但是我们的计算是从10开始的,所以要减去f[2][0]
对于100-120,它是奇数位数,所以利用之前得到的性质,计算100-120之间有多少个“数对”,显然这一段对答案的贡献为(120-1-100)/2-1+2-0(最后的120是孤立的,单独计算即可)
对2456来说,形同上计算0-9,10-99,100-999,最后计算1000-2456,这是偶数位数,我们可以继续把它分解成1000-1999(即f[4][1]-f[4][0]),2000-2399(即f[3][3]-2*400),2400-2449(即f[2][4]-2*50+4*50)最后计算时要在个位特判一下,普遍规律就是可以记录一下前边的数数字按位计算的和差×10的几次方×当前位数字(这里有些口胡,因为不是很(想+会)用式子表达)
注意:
还是补充一下个位特判好了,例如计算2400时,在十位的0是不计算的,但个位的0也是一次计算,所以要计算
代码:
#include<bits/stdc++.h> #define LL long long using namespace std; LL x,k,n,ans; LL p[20]={1},s[20]={0,5,0,450},f[20][10],wei[20]; LL fj(LL x) { LL ans=0; for (int i=1;i<=20;i++) { if (!x) return ans; if (i&1) ans+=x%10; else ans-=x%10; x/=10; } } main() { scanf("%lld",&n); for (int i=1;i<=17;i++) p[i]=p[i-1]*10;//p[i]=10^i for (int i=5;i<=17;i+=2) s[i]=s[i-2]*100;//5,450,45000…… for (int i=1;i<=17;i++) for (int j=0;j<=9;j++) { if (!j) f[i][j]=f[i-1][9]; else if (i&1) f[i][j]=f[i][j-1]+f[i-1][9]+p[i-1]*j; else f[i][j]=f[i][j-1]+f[i-1][9]-p[i-1]*j; } for (int i=1;i<=16;i++) { if (p[i]>n) {k=i-1;break;} if (i&1) ans=ans+s[i]; else ans=ans+f[i][9]-f[i][0]; } if (k&1) { LL q=0,now=n; for (int i=1;i<=k+1;i++) wei[i]=now%10,now/=10; ans-=f[k+1][0]; for (int i=k+1;i>=1;i--) { if (wei[i]||i==1) ans=ans+q*(wei[i]+(i==1))*p[i-1]+f[i][wei[i]+(i==1)-1]; if (i&1)q+=wei[i]; else q-=wei[i]; } } else { if (n&1) ans+=(n-p[k])/2+1; else ans=ans+(n-p[k]+1)/2-fj(n); } printf("%lld",ans); }
相关文章推荐
- R文件无法自动生成
- 前端经验技巧谈论
- C和C++语言&
- mybitis常见问题汇总中....
- python学习(九):异常、调式与测试
- thinkpad T450, 按Fn+ESC键实现F1,F2,..F10输入的模式变换
- update select
- ios模拟器键盘不弹出
- 多线程
- 题目1049:字符串去特定字符
- 【cocos2d-x制作别踩白块儿】第一期:游戏介绍
- 2016年,C语言该怎样写
- JVM--垃圾收集器
- 设置 滚动条 宽度为0
- HTML-文本格式化
- 投米变现外挂下载和使用教程独家
- 图像特征提取之(一)HOG特征
- requests上传文件
- 基于Smusic开源播放器的改版播放器 LKMusic正式开工
- Everything常见问题及搜索技巧,附Demo