求n个数的LCM(最小公倍数)并对1e9+9取模

题目:

沿着河边看一看清冷的夏夜,耳机里是AR的《呼兰河传》。AR的呼兰河并非一条河,而是一个故乡小城的生活日记。静谧的童年,孩子看世界的眼光,花开鸟飞间的自由,塑造了一方那个时代中少有的美好。现在,你需要回答以下问题,才可倾听这首《呼兰河传》带来的温柔,试试吧。给你n个数,选择一些数,使得LCM最大,输出LCM的最大值并对1e9+9取模。

输入描述:

第一行输入一个n,代表数字的个数。
第二行输入n个数a[i],代表每个数的值。

1<=n<=1e6,1<=a[i]<=1e5。

输出描述:

选择一些数能得到的最大LCM,由于LCM太大了,你只需要对1e9+9取模即可。

思路:

显然把所有数字都选的LCM一定是最大的,直接求所有数的LCM即可
直接做LCM的话在取模的时候会出现错误,不能直接求n个数字的LCM
转化为质因数分解,对于每个质因子取最高次幂的结果就是最终的答案
例如 2, 4, 6, 8分别是 2, 2^2, 2∗3, 2^3
最终答案就是 2^3*3
注意一些优化细节,提前做一下素数筛,以及在质因数分解的时候不用跑满所有质因子
然后是数组不必开1e6, 边读边分解就行

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 9;
const int N = 2e5 + 9;
int prime[N], p[N], cnt, mp[N], ans[N];

void Init()
{ //素数筛
	int len = sqrt(1e5);
	for (int i = 2; i <= len; i++)
	{
		if (!prime[i])
		{
			p[++cnt] = i;
			mp[i] = cnt;
			for (ll j = 2 * i; j <= len; j += i)
				prime[j] = 1;
		}
	}
}

ll quick_pow(ll a, ll b)
{ //快速幂
	ll res = 1;
	while (b)
	{
		if (b & 1)
			res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

int main()
{
	int n;
	Init();
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		int pre;
		cin >> pre;
		for (int j = 1; j <= cnt && pre >= p[j]; j++)
		{
			int cur = 0;
			if (pre % p[j] == 0)
			{
				while (pre % p[j] == 0)
				{
					++cur;
					pre /= p[j];
				}
			}
			ans[j] = max(ans[j], cur);
		}
		if (pre > 1)
		{
			int j = 0;
			if (!mp[pre])
			{
				p[++cnt] = pre;
				mp[pre] = cnt;
				j = cnt;
			}
			else
				j = mp[pre];
			ans[j] = max(1, ans[j]);
		}
	}
	ll res = 1;
	for (int i = 1; i <= cnt; i++)
	{
		res *= quick_pow(p[i], ans[i]);
		res %= mod;
	}
	cout << res << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xmyrzb/article/details/106909993