NOIP模拟 阶乘(质因数分解+二分答案)

【题目描述】

有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值。

【输入格式】

共两行。

第一行一个正整数n。

第二行n个正整数a[i]。

【输出格式】

共一行

一个正整数m。

【样例输入】

1

6

【样例输出】

3

【备注】

对于10%的数据,n<=10

对于30%的数据,n<=1000

对于100%的数据,n<=100000,a[i]<=100000

【题目分析】

这是第几次被二分答案上界给neng死了。。。10分滚粗。。。

首先可以先将p分解质因数,可以推出最后m!一定是包含了p的所有质因子的。

所以就可以二分m的值(上界要设很大,否则如果出现100000个相同数(或类似这种情况),最后m值就会很大),判断一下是否包含p,如果可以就下调,否则上调。

【代码~】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=100010;

LL P[maxn],s1[maxn],s2[maxn];
LL tot,n,a,last;
bitset<maxn> isprime;

void pre()
{
	isprime[0]=isprime[1]=1;
	for(LL i=2;i<=100000;++i)
	{
		if(!isprime[i])
		{
			for(LL j=i+i;j<=maxn;j+=i) 
			  isprime[j]=1;
			P[++tot]=i;
		}
	}
}

LL check(LL x)
{
	memset(s2,0,sizeof(s2));
	for(LL i=1;P[i]<=x&&i<=tot;++i)
	{
		LL tmp=x;
		while(tmp)
		{
			tmp/=P[i];
			s2[i]+=tmp;
		}
	}
	for(LL i=1;i<=last;++i)
		if(s1[i]>s2[i]) 
		  return false;
	return true;
}

void fj(LL x)
{
	if(x==1||x==0) 
	  return;
	for(LL i=1;P[i]<=x&&i<=tot;++i)
	{
		while(x%P[i]==0)
		{
			x/=P[i];
			s1[i]++;
		}
		last=max(last,i);
	}
}

int main()
{
	pre();
	scanf("%lld",&n);
	for(LL i=1;i<=n;++i)
	{
		scanf("%lld",&a);
		fj(a);
	}
	LL l=1,r=100000000000;
	while(l<r)
	{
		LL mid=l+r>>1;
		if(check(mid)) 
		  r=mid;
		else 
		  l=mid+1;
	}
	printf("%lld",l);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/82943476