P3927 SAC E#1 - 一道中档题 Factorial
2017-10-10 19:52
357 查看
题目背景
数据已修改
SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友。题目描述
SOL君很喜欢阶乘。而SOL菌很喜欢研究进制。这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘。
SOL菌表示不服,立刻就要算这个数在k进制表示下末尾0的个数。
但是SOL菌太菜了于是请你帮忙。
输入输出格式
输入格式:每组输入仅包含一行:两个整数n,k。
输出格式:
输出一个整数:n!在k进制下后缀0的个数。
输入输出样例
输入样例#1:10 40
输出样例#1:
2
说明
对于20%的数据,n <= 1000000, k = 10对于另外20%的数据,n <= 20, k <= 36
对于100%的数据,n <= 10^12,k <= 10^12
update
1.一组数据2.K不会==1
3.现在std没有爆long long
4.对数据有问题联系icy (建议大家不要面向数据编程)
这道题如果用传统的方法去做,似乎只能做20%的分。
不过我们换个角度想,
先取比较熟悉的例子,N!在十进制下末尾零的个数,即求N!中包含的2和5的个数的最小值。(显然每一个末尾零都需要2和5相乘来得到)
那么N!在K进制下末尾零的个数,也等价于是N!中包含的K的质因数的最小个数。(K进制含义就是逢K进1,此时便产生一个末位0)
这样一来,我们就可以先用筛法求出质数,然后再求K的质因数即每个质因数的个数。
求k的质因数只需求1~根号k的质因数,因为若k为合数,其至少有一个质因数在1~根号k之间,而最多只有一个大于根号k的质因数。
所以当最后 t!= 1时, t 必为 唯一一个大于 根号k的质因数(k必然不存在两个大于根号k的质因数),需要考虑。
然后求N!中的每个质数i的个数即为
这个不难看出,因为N!=N*(N-1)*(N-2)……*2*1
其中k就含有一个k的因数,k*k含有两个,以此类推。
最好ans初始值应为一个极大的数,如(1ll << 60)
#include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 0; inline int get(){ char c; while((c = getchar()) < '0' || c > '9'); int cnt = c - '0'; while((c = getchar()) >= '0' && c <= '9') cnt = cnt * 10 + c - '0'; return cnt; } typedef long long LL; const LL maxn = 1E6; LL N,K,ans,totc=0; LL cnt[maxn+10],a[maxn+10]; bool b[maxn+10]; int pr[maxn+10],totp=0; int main(){ #ifdef lwy freopen("in.txt","r",stdin); /* #else freopen(".in","r",stdin); freopen(".out","w",stdout);*/ #endif memset(cnt,0,sizeof(cnt)); memset(a,0,sizeof(a)); memset(b,true,sizeof(b)); scanf("%lld %lld",&N,&K); LL t = K; totc = sqrt(K); for(int i = 2; i <= totc; i++){ if(b[i]) pr[++totp] = i; for(int i = 1; i <= totp; i++){ if(i * pr[i] > totc) break; b[i * pr[i]] = false; if(i % pr[i] == 0) break; } } for(int i = 1; i <= totp; i++){ while(t % pr[i] == 0){//if(t % pr[i] == 0) t /= pr[i]; cnt[i]++; } } if(t != 1){ pr[++totp] = t; cnt[totp] = 1; } for(int i = 1; i <= totp; i++){ LL k = pr[i]; while(k <= N){ a[i] += N / k; k *= pr[i]; //k *= k; } } ans = (1LL << 60); for(int i = 1; i <= totp; i++){ LL k; if(cnt[i] == 0) continue; k = a[i] / cnt[i]; ans = min(ans,k); } printf("%lld",ans); return 0; }
原理虽然简单,但编写过程中出了两处//后的错误。
网上发现有直接计算每个数而不分质因数考虑的解法,大体原理是相同,但是去除了找质数的操作,所以更快些。
需要注意的是最后 t != 1 的情况,此时 t 为 大于 根号k的质数,也是k的一个质因数,需要考虑。
找错的时候用了对拍,
数据生成器
注意要使用<ctime>库,以及需要用srand(0)初始化随机函数
rand()∈[0,2^16) 可以根据需要调整。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;
const int MAXN = 0;
inline int get(){
char c;
while((c = getchar()) < '0' || c > '9');
int cnt = c - '0';
while((c = getchar()) >= '0' && c <= '9') cnt = cnt * 10 + c - '0';
return cnt;
}
int main(){
/* #ifdef lwy
#else
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif*/
srand(time(0));
long long N,K;
N = rand() >> 10;
while(K == 1 || K == 0) K = rand() >> 10;
printf("%lld %lld",N,K);
return 0;
}
对拍代码如下,相应文件应提前建立,并且每个程序都应先编译好。
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<windows.h>
using namespace std;
const int MAXN = 0;
inline int get(){
char c;
while((c = getchar()) < '0' || c > '9');
int cnt = c - '0';
while((c = getchar()) >= '0' && c <= '9') cnt = cnt * 10 + c - '0';
return cnt;
}
int main(){
/* #ifdef lwy
#else
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif*/
int t = 100;
while(t--){
system("data > in.txt");
system("1 < in.txt > 1.out");
system("2 < in.txt > 2.out");
if(system("fc 1.out 2.out")) break;
}
system("pause");
return 0;
}
相关文章推荐
- 洛谷 P3927 SAC E#1 - 一道中档题 Factorial
- 【P3927】SAC E#1 - 一道中档题 Factorial(luogu八连刷R1提高组)
- 【Luogu】P3927 SAC E#1 - 一道中档题 Factorial
- 洛谷P3927 SAC E#1 - 一道中档题 Factorial
- SAC E#1 - 一道中档题 Factorial
- 【洛谷10月月赛R1提高组】 SAC E#1 - 一道中档题 Factorial
- LuoguP3927 SAC E#1 - 一道中档题 Factorial 解题报告【唯一分解定理】
- 洛谷10月月赛R1·浴谷八连测R1·提高组 SAC E#1 -T1 一道中档题 Factorial
- 洛谷10月月赛R1·浴谷八连测R1·提高组 SAC E#1 - 一道中档题 Factorial
- noip模拟赛 SAC E#1 - 一道中档题 Factorial
- 洛谷10月月赛R1T1-SAC E#1 - 一道中档题 Factorial(pollard-rho质因数分解)
- LuoguP3927 SAC E#1 - 一道中档题 Factorial
- [luogu3927] SAC E#1 - 一道中档题 Factorial
- 【luogu10月月赛】一道中档题 Factorial(数论)
- SAC E#1 - 一道中档题 Factorial
- 洛谷10月月赛R1·浴谷八连测R1·提高组 一道中档题 Factorial
- 洛谷10月月赛R1-T1-一道中档题 Factorial
- [洛谷P3927]一道中档题
- 洛谷3927 一道中档题
- P3928 SAC E#1 - 一道简单题 Sequence2