【二分】阶乘

https://ac.nowcoder.com/acm/contest/4784/B
给定一个正整数 p
求一个最小的正整数 n,使得 n ! 是 p 的倍数

输入描述:

第一行输入一个正整数 T 表示测试数据组数
接下来 T 行,每行一个正整数 p

输出描述:

输出 T 行,对于每组测试数据输出满足条件的最小的 n

在这里插入图片描述
比赛思路:
比赛的时候思路错了,还以为考的是高精度,因为感觉阶乘会很大… 所以一开始把把每个数的阶乘递推 存到邻接表里,这样就可以存很大的数然后每次遍历数组看能不能整除p,最后输出数组下标i就好了…实际就是个假的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const double eps=1e-8;
ll x,y,z,n,k,t,m,p,maxs=0;
template<typename T>inline void read(T &x){
    x=0; int f=1;char c=getchar();
    while(c<'0'||c>'9') if(c=='-') f=-1,c=getchar();
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x*=f;
}
int check(int x,int y,int cnt){
	int ans=0;
	while(x){
		ans+=x/y;
		x/=y;
	}
	return ans>=cnt;
}
ll bi(int x, int cnt) {
	int left = 1, right = 1e9;
	while(left <= right) {
		int mid = (left + right) >> 1;
    	if(check(mid, x, cnt)) {
			right = mid - 1;
    	} else {
			left = mid + 1;
    	}
	}
	return right+1;
}
int main(){
//	ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
	read(t);
	while(t--){
		read(p);
		ll ans=0;
		for(int i=2;i*i<=p;i++){
			if(p%i==0){
				ll cnt=0;
				while(p%i==0){
					p/=i;
					cnt++;
				}
				ans=max(ans,bi(i,cnt));
			}
		}
		ans=max(ans,p);
		printf("%lld\n",ans);
	}
} 

题解思路:
利用类似于埃式筛法的思想,将p进行质因数分解,
每次看能被 i 除几次,然后进入函数bi,bi函数就是进行二分的函数,找n,看看他的阶乘里有多少个因子i ,
如果当前的n里的因子i的数目大于cnt,那么就缩小范围,
函数check的作用就是找n!里因子的个数,
最后找到符合n!里的因子数>=cnt的最小的 n。

然后每次max更新答案,
这样子得到的n才能满足所有的因子数都 >= cnt。
最后还有一步:

ans=max(ans,p);

如果p=1的话就进入不了循环,这样直接ans=p=1了;
如果p为质数的话,就没有任何因子,所以最小的ans=p,只有p!才能是p的倍数

在这里插入图片描述

发布了62 篇原创文章 · 获赞 0 · 访问量 650

猜你喜欢

转载自blog.csdn.net/weixin_44745441/article/details/105065731