阶乘

题目大意

nn 个正整数 aia_i,设它们乘积为 pp,你可以给 pp 乘上一个正整数 qq,使 pqp*q 刚好为正整数 mm 的阶乘,求 mm 的最小值。

对于 100%100\% 的数据,n<=100000ai<=100000n<=100000,a_i<=100000

解题思路

根据题目可得,根据整数的唯一分解式,m=a1p1a2p2a3p3  ...m=a_1^{p_1}*a_2^{p_2}*a_3^{p_3} \ \ ...,其中 aia_i 为质数。

方法一

根据上式,pp 也可以分解,那么最小的 mm 只需满足包含所有 aipia_i^{p_i} 就行了。

看一个数 xx 中有多少的 tt 的方法。

f(x,t)=xt+xt2+xt3+ ...f(x,t)=\left\lfloor\dfrac{x}{t}\right\rfloor + \left\lfloor\dfrac{x}{t^2}\right\rfloor + \left\lfloor\dfrac{x}{t^3}\right\rfloor + \ ...

加到有 00 为止就行了。

采用二分答案,二分 mm,使 mm 满足上面的要求。

时间复杂度为 O(求所有因子+nlogn)O(求所有因子 + n \log n)

AC CODE

方法一

#include<bits/stdc++.h>
using namespace std;

#define int long long

int read()
{
	int x = 0, f = 1;
	char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		x = x * 10 + c - 48;
		c = getchar();
	}
	return x * f;
}

int n;

int mmax;

int ans = 0;

int a[100005];

void kkk(int x)
{
	int xx = x;
	for(int i = 2; i * i <= xx; ++i)
	{
		if(xx % i == 0)
		{
			while(x % i == 0)
			{
				x /= i;
				a[i]++;
			}
		}
	}
	if(x) a[x]++;
}

int wjy(int x, int y)
{
	int j = y;
	int res = 0;
	while(x >= j)
	{
		res += x / j;
		j = j * y;
	}
	return res;
}

bool check(int mid)
{
	for(int i = 2; i <= mmax; ++i)
		if(wjy(mid, i) < a[i]) return false;
	return true;
}

signed main()
{
	n = read();
	for(int i = 1; i <= n; ++i)
	{
		int x;
		x = read();
		kkk(x);
		mmax = max(mmax, x);
	}
	int l = 1, r = 1e9;
	while(l <= r)
	{
		int mid = (l + r) >> 1;
		if(check(mid))
		{
			ans = mid;
			r = mid - 1;
		}
		else
		{
			l = mid + 1;
		}
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2021-09-20 14:30  蒟蒻orz  阅读(3)  评论(0编辑  收藏  举报  来源