[题解] 完美数

题目大意

给定 \(n\) 个数字,将这 \(n\) 个数字乘起来。找到 \(1\) 个数字 \(k\) ,使得 \(k!\) 能被 \(n\) 整除。求最小的 \(k\)

思路

先将 \(n\) 个数字分别质因数分解,用桶 \(B1\) 把这些质因数的个数统计起来。

按照题目的意思,需要找到一个 \(k!\) ,将其质因数分解,也把分解的这些质因数装进另一个桶 \(B2\) 里,使得桶 \(B2\) 里所有元素的个数都大于桶 \(B1\) 里面所有元素的个数。

怎么来找这个桶呢?可以二分枚举,找出答案。

这里分享另一种做法。

对于桶里面的每一个元素,都可以找到 \(1\) 个最小满足含有这个元素的乘积的倍数。描述有一些模糊,举个例子:

\(2\) 个数字,\(81\)\(45\)。将这两个数字分解,则桶 \(B1\) 里,\(3\) 的个数为 \(6\)\(5\) 的个数为 \(1\) 。则最小满足 \(6\)\(3\) 的数字为 \(15\)。其中, \(3\)\(1\) 个贡献, \(6\)\(1\) 个贡献, \(9\)\(2\) 个贡献, \(12\)\(1\) 个贡献, \(15\)\(1\) 个贡献。简单来说,这个数字含有多少个 \(3\) ,就做多少贡献。可以直接暴力枚举,枚举到满足条件即可,这个数据枚举到 \(15\) 。对于 \(5\) 同理,枚举到 \(5\) 即可。最后取这两个数的最大值,因为 \(15!\) 就包含了 \(5!\) ,而且两质数之间互不干扰,没有交集。故而答案为 \(15\)

总结

先用桶存储这 \(n\) 个数字的质因数个数,找桶中每个元素,满足这个元素的最小的 \(k\) ,取最大值来满足条件即可。

C++代码

#include <cstdio>
#define Max(a, b) ((a) > (b) ? (a) : (b))
void Quick_Read(int &N) {
	N = 0;
	int op = 1;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-')
			op = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		N = (N << 1) + (N << 3) + (c ^ 48);
		c = getchar();
	}
	N *= op;
}
const int MAXN = 1e5 + 5;
int bucket[MAXN];
bool flag[MAXN], vis[MAXN];
int p[MAXN];
int n, cnt, num;
void Primes() {
	int k = 100000;
	flag[1] = 1;
	for(int i = 2; i <= k; i++) {
		if(!flag[i])
			p[++cnt] = i;
		for(int j = 1; p[j] * i <= k && j <= cnt; j++) {
			flag[p[j] * i] = true;
			if(i % p[j] == 0)
				break;
		}
	}
}
int main() {
	int A;
	Primes();
	Quick_Read(n);
	for(int i = 1; i <= n; i++) {
		Quick_Read(A);
		for(int j = 1; j <= cnt && A != 1; j++) {
			if(A <= 100000 && !flag[A])
				break;
			while(A % p[j] == 0) {
				A /= p[j];
				bucket[p[j]]++;
				if(!vis[p[j]])
					num++;
				vis[p[j]] = true;
			}
		}
		if(!vis[A] && A != 1)
			num++;
		vis[A] = true;
		bucket[A]++;
	}
	int ans = 0;
	for(int i = 2; i <= 100000; i++) {
		if(!bucket[i])
			continue;
		int j = 0, product, maxn = 0;
		while(bucket[i] > 0) {
			j++;
			product = j * i;
			while(product % i == 0) {
				product /= i;
				bucket[i]--;
			}
			maxn++;
		}
		ans = Max(ans, maxn * i);
	}
	printf("%d", ans);
	return 0;
}
posted @ 2020-12-19 14:06  Last_Breath  阅读(172)  评论(0编辑  收藏  举报