[NOIP模拟]Factorial Surplus Tail
来源:互联网 发布:剑三秀姐捏脸数据 编辑:程序博客网 时间:2024/05/16 17:51
题目描述:
FST 作为 OIer ,经常会遇到和阶乘有关的问题,但是一个数的阶乘末尾总是会有很多 0 ,FST 认为这很不美观,但是 FST 觉得如果 0 的个数是偶数的话,还是可以接受的。
所以就有这样一个问题,FST 想知道
输入格式:
读入有若干行,每行一个正整数 n ,最后一行是一个 -1 。
输出格式:
对于每个 n 输出一行,为
样例输入:
2
3
10
-1
样例输出:
3
4
6
数据范围:
测试点 1、2:n≤10;数据组数=1;
测试点 3、4:n≤10000;数据组数=10;
测试点 5、6、7、8:n≤
测试点 9、10:n≤
题目分析:
找规律+dp。表示不看题解,很难找到这个规律。
第一次 DP,预处理计算[0,
k=0: 0
k=1: 00000
k=2: 0000011111000001111100000
k=3: 0000011111000001111100000(重复五遍···)
有 2 种可能:
k是奇数,那么 k-1是偶数,0 个数的奇偶不会变,
k是偶数, 那么 k-1是奇数, 0 个数的奇偶会变,
值得注意的是,我们表示的是从0开始,比如k=2,表示的是从0~24,k=3是0~124,这在后面会决定处理的方法。
如果你要问我这规律是怎么发现的,那我只能说是题解告诉我的(不,其实是无可奉告>_<)。
部分代码:
void prework()//一切皆如上述解释{ mi[0]=1; for(int i=1;i<=25;i++) mi[i]=mi[i-1]*5; num[0][0]=1; //k=0时 for(int i=1;i<=25;i++) { if(i%2==1) { num[i][0]=num[i-1][0]*5;//分别记录了0、1的个数 num[i][1]=num[i-1][1]*5; } else { num[i][0]=3*num[i-1][0]+2*num[i-1][1]; num[i][1]=3*num[i-1][1]+2*num[i-1][0]; } }}
第二次 DP,把 n+1 转化为 5 进制,从高位开始做。
然后我们可以分类讨论,例如当前位的数是 3,当前位是奇数位,现在的奇偶性为偶,那么转移答案为
如果你没看懂,这很正常。如果你一眼就看懂了,orz大佬。
先放代码:
ans=0;tmp=0;for(int i=25;i>=0;i--)//相当于在拆成五进制数,从高位做起{ for(int j=1;j<=(n/mi[i]);j++) { ans+=num[i][tmp]; if(i%2==1) tmp^=1;//根据五的几次方,奇次方,要正反正的反转 } n%=mi[i];}ans+=num[0][tmp];//因为我们预处理的是[0~5^k),假如我们询问125,上面代码虽然处理了125个数,但是算的是0~124,125还要单独算一下printf("%I64d\n",ans);
首先解释为什么这里变成了奇次方会出现反转(上面我复制的那段题解中说的是奇数位反转,根据题解代码来讲,我觉得应该题解说错了,因为奇数位对应的是偶数次方),而第一次dp是偶数k才反转。考虑一个数329,它化成五进制为2301,对于最高位2,它虽然是329除以125得到的。但是范围是在k=4里,所以会反转。
最后再模拟一下,还是329:首先除以125的得到2(余79),然后因为i%2==1(此时i=3),所以会要反转的情况,即第一段是k=3(答案加k=3的0的个数),第二段是k=3取反(答案加k=3的1的个数)。剩余79除以25得3(余4),i%2==0······直到最后。
注意tmp是接着用的,因为上一段的tmp会影响这里。比如我们第一次处理奇次方(假设此时是大于k=3,小于k=4),那么我们询问的就是k=4的一部分,假设处理了三段(利用k=3),正反正,然后还剩余一截,其实是剩在了第4段里(这一段是要反转的),虽然我们剩余部分的处理要利用k=2,但这里要反转,所以tmp要接着用才能让它是反转的,否则你tmp重置为0,就不会把其反转。
附代码:
#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<ctime>#include<queue>#include<set>#include<map>#include<cctype>#include<iomanip>#include<cmath>#include<algorithm>using namespace std;long long n,mi[100],ans,num[100][2],tmp;long long readlong(){ char ch;long long i=0,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') {ch=getchar();f=-1;} for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0'; return i*f;}void prework(){ mi[0]=1; for(int i=1;i<=25;i++) mi[i]=mi[i-1]*5; num[0][0]=1; for(int i=1;i<=25;i++) { if(i%2==1) { num[i][0]=num[i-1][0]*5; num[i][1]=num[i-1][1]*5; } else { num[i][0]=3*num[i-1][0]+2*num[i-1][1]; num[i][1]=3*num[i-1][1]+2*num[i-1][0]; } }}int main(){ //freopen("fstagain.in","r",stdin); //freopen("fstagain.out","w",stdout); prework(); while(n=readlong(),n!=-1) { ans=0;tmp=0; for(int i=25;i>=0;i--) { for(int j=1;j<=(n/mi[i]);j++) { ans+=num[i][tmp]; if(i%2==1) tmp^=1; } n%=mi[i]; } ans+=num[0][tmp]; printf("%I64d\n",ans); } return 0;}
- [NOIP模拟]Factorial Surplus Tail
- [NOIP2017模拟]Factorial Surplus Tail
- php 模拟 tail -f
- Noip模拟
- 【NOIP模拟】20151004模拟
- 【NOIP模拟】 20151005模拟
- 【NOIP模拟】 20151006模拟
- 【NOIP模拟】 20151007模拟
- 【NOIP模拟】20151014模拟
- 【NOIP模拟】20151015模拟
- Codewars进阶之路——Factorial tail
- 【09 NOIP 模拟】light
- [NOIP模拟]Day1
- 8.9CH NOIP模拟
- 8.10FCH NOIP模拟
- 8.13NOIP模拟
- 8.14NOIP模拟
- noip模拟赛 双城记
- 欢迎使用CSDN-markdown编辑器
- 原来Android触控机制竟是这样的?
- APP 跳转高德地图
- 4.4 leetcode -4 symmetric-tree
- Linux环境下升级openssl步骤
- [NOIP模拟]Factorial Surplus Tail
- 今日群更新:20天JAVA基础从入门到精通
- maven项目模板
- 完美的sharedPreference工具类
- weblogic10.3.6部署war包时出现weblogic.descriptor.DescriptorException: VALIDATION PROBLEMS WERE FOUND
- Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
- (dp)正整数分组
- java验证邮箱地址是否正确
- JavaScript 产生不重复的随机数三种实现思路