牛客 - 阶乘(唯一分解定理)

题目链接:点击查看

题目大意:给出一个 p ,求出最小的 n! 使得 p 可以整除 n!

题目分析:因为 p 高达 1e9 ,可以考虑sqrt(n)的算法,也就是唯一分解定理了,分解之后对于每个质因子,我们可以单独讨论,对于某个质因子 p[ i ] ,记录其在 p 中的出现次数 num[ i ] ,我们现在只需要找到一个最小的 k ,使得 k! 内含有大于等于 num[ i ] 个 质因子p[ i ] 即可,然后用答案维护一下 k 的最大值就是答案了

这样问题就转换为了如何找到这个最小的 k ,这里提供两种思路:

第一种思路就是直接二分,因为显然此处的 k 具有单调性,我们的check函数也只需要找 [ 1 , k ] 内一共含有多少个 p[ i ] 就好了

第二种思路就是直接枚举,因为如果都是基于 2 这个质因子,那么 num 最多也只有  30 ,所以不难看出,所有质因子数量之和一定是小于 30 的,这样我们就可以直接枚举了,对于某个质因子 p[ i ] ,每次都加上 p[ i ] 然后计算答案就好了

代码:这里给出第二种思路实现

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
      
typedef long long LL;

typedef unsigned long long ull;
      
const int inf=0x3f3f3f3f;
 
const int N=1e5+100;

int main()
{
#ifndef ONLINE_JUDGE
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		int n;
		scanf("%d",&n);
		int ans=-1;
		for(int i=2;i*i<=n;i++)
			if(n%i==0)
			{
				int cnt=0;
				while(n%i==0)
				{
					n/=i;
					cnt++;
				}
				int k=0;
				for(int j=i;;j+=i)//枚举最小的 k 
				{
					int num=j;
					while(num%i==0)
					{
						num/=i;
						k++;
					}
					if(k>=cnt)
					{
						ans=max(ans,j);
						break;
					}
				}
			}
		printf("%d\n",max(ans,n));
	}
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
}
发布了700 篇原创文章 · 获赞 29 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/105020589