0829-T3 公因数

0829-T3 公因数

题意

给定一个长度为 n 的序列,可以做若干次操作。

每次操作选择两个数 A,B,选择 A 的一个质因数 P,将 A 变为 AP,将 B 变为 BP

求经过若干次操作后序列最大公因数的最大值,以及此情况下操作的最小次数。

思路

每次操作不会改变序列总共的质因数和次数。

想要最大公因数最大,必须让质因数的次数平均分配给每个数。

现将每个数都质因数分解,次数加起来。

容易发现每个质因数的次数 c,对答案的共献为 cn

对于操作次数,如果 Ai 的质因数 pi 的次数为 ci,并且 ci 小于答案中 pi 的次数 Ci,对答案就有贡献。

Ai 至少会操作 Cici 次把外面的质因数 pi 收集回来,答案加上 Cici

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, a[N], c[N], ans1 = 1, ans2; 
int q[N], tot, b[N];
int qpow(int a, int p) {
	int res = 1;
	for (; p; p >>= 1, a *= a)
		if (p & 1) res *= a;
	return res;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i ++) cin >> a[i];
	for (int i = 1, t; i <= n; i ++) {
		t = a[i];
		for (int j = 2; j * j <= a[i]; j ++) {
			if (t % j) continue;
			if (!c[j]) q[++ tot] = j;
			while (t % j == 0) t /= j, c[j] ++;
		}
		if (t != 1) {
			if (!c[t]) q[++ tot] = t;
			c[t] ++;
		}
	}
	for (int i = 1; i <= tot; i ++) c[q[i]] /= n;
	for (int i = 1; i <= tot; i ++) ans1 *= qpow(q[i], c[q[i]]);
	for (int i = 1, t; i <= n; i ++) {
		t = a[i];
		for (int j = 2; j * j <= a[i]; j ++) {
			if (t % j) continue;
			while (t % j == 0) t /= j, b[j] ++;
		}
		if (t != 1) b[t] ++;
		for (int j = 1; j <= tot; j ++) ans2 += max(0, c[q[j]] - b[q[j]]);
		t = a[i];
		for (int j = 2; j * j <= a[i]; j ++) {
			if (t % j) continue;
			while (t % j == 0) t /= j, b[j] --;
		}
		if (t != 1) b[t] --;
	}
	cout << ans1 << " " << ans2 << "\n";
	return 0;
}
posted @   maniubi  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示