牛客小白月赛23 B 阶乘题解(二分+质因数分解)

题目链接

题目大意

给定一个正整数p,求一个最小的正整数 n,使得 n! 是 p 的倍数

题目思路1

看到此题还是会想到质因数分解,但是没想到是需要p和n!都要质因数分解。可以把p分解的因子和次数用

一个pair储存。然后可以发现其实这个题目是满足二分条件的。

注意n质因数分解时那个变量j要设为long long 。因为可能会爆int,有关i,j在for循环里面是乘法操作的一定要注意很容易wa

代码1

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int inf=0x3f3f3f3f;
const int maxn=1e3;
int t,p,cnt;
pair<int,int> a[maxn];
bool check(int x){
	for(int i=1;i<=cnt;i++){
		int sum=0;
		for(ll j=a[i].first;j<=x;j=j*a[i].first){//唯一分解定理 ,j可能会爆int 
			sum=sum+x/j;
		}
		if(sum<a[i].second){//不满足 
			return false;
		}
	}
	return true;
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&p);
		int temp=p;
		cnt=0;
		memset(a,0,sizeof(a));
		for(int i=2;i*i<=p;i++){
			if(p%i){//不可以整除 
				continue;
			}
			a[++cnt].first=i;//first代表因子 
			while(p%i==0){
				a[cnt].second++;//second代表有几个first 
				p=p/i;
			}
		}
		if(p!=1){//p为质数 
			a[++cnt].first=p;
			a[cnt].second=1; 
		}
		int l=1,r=temp,ans=inf;
		while(l<=r){
			int mid=(l+r)/2;
			if(check(mid)){//注意题目要求 
				ans=min(ans,mid);
				r=mid-1;
			}else{
				l=mid+1;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

题目思路2

其中p1,p2,…,pn为互不相同的质数。那么我们对每个质数pi,找到能凑到指数ki的最小数字,比如pi=2,ki=2,那么2含有1个2因子,

4含有2个2因子,加起来为3>=2,所以凑成2^2至少要4!。我们对每个质数都进行这样的一次寻找,ans保存最大的那个就行了。

则不需要二分

代码2

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int p,t,cnt,j;
map<int,int> a;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&p);
		int ans=1;
		for(int i=2;i*i<=p;i++){
			if(p%i){
				continue;
			}
			int sum=0;
			while(p%i==0){//表示有sum个i因子 
				p=p/i;
				sum++;
			}
			a.clear();//清空 
			for(j=1,cnt=0;cnt<sum;j++){//这段代码有点神仙,自己演算一下就知道 
				a[j*i]=a[j]+1;
				cnt=cnt+a[j*i]; 
			}
			ans=max(ans,i*(j-1));//注意是j-1	
		}
		ans=max(ans,p);//这个不要忘,因为p可能自己也是一个质数 
		printf("%d\n",ans);
	}
	return 0;
}
发布了68 篇原创文章 · 获赞 2 · 访问量 2249

猜你喜欢

转载自blog.csdn.net/m0_46209312/article/details/105224167