CF-Round #641-div2-C题&div1A题

CF-Round #641-div2-C题&div1A题

C. Orac and LCM

传送门

这道题是关于lcm和gcd的题目~

题目大意:让你求所给数组中所有两两数字的最小公倍数的最大公约数。

本题思路:
我们要求这些数字的最小公倍数的最大公约数。
比如我们求数组a[] = {x, y, z};这三个数的两两数字间的最小公倍数的最大公约数。
我们先来解决关于每个数的最小公倍数的最大公约数。(最后我们只用求这些数的最大公约数即可)
关于x的最小公倍数:gcd(x * y / gcd(x, y), x * z / gcd(x, z));
提取出x。
x * gcd(y / gcd(x, y), z / gcd(x. z));
对于gcd(y / gcd(x, y), z / gcd(x. z))
我们把这个式子的y, z提取出来;
变成了:
gcd(y, z) / gcd(gcd(x, y), gcd(x, z));
进一步化简:
gcd(y, z) / gcd(x, y, z);
相当于我们求把gcd(y / gcd(x, y), z / gcd(x. z))转化为gcd(y, z)时扩大了gcd(gcd(x, y), gcd(x, z))倍。
然后我们观察gcd(y, z) / gcd(x, y, z);
可以发现,维护一下后缀gcd就可以啦~
然后我们后面就可以直接以此类推啦~
我们从后往前向后计算。
先计算最后一个数的最小公倍数的最大公约数。最后一个数的gcd就是自己本身嘛(向后计算,这样的顺序可以保证全部都计算到)
然后往前走,更新ans即可。

suf[]数组是计算后缀的gcd的~

代码部分:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;

ll a[N];
ll suf[N];

ll gcd(ll a, ll b)
{
	if (!b)
	{
		return a;
	}
	return gcd(b, a % b);
}

int main()
{
	int n;
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		scanf ("%I64d", &a[i]);
	}
	suf[n] = a[n];
	for (int i = n - 1; i >= 1; i--)
	{
		suf[i] = gcd(suf[i + 1], a[i]);
	}
	ll ans = 1ll * a[n] * a[n - 1] / suf[n - 1];
	for (int i = n - 2; i >= 1; i--)
	{
		ans = 1ll * gcd(ans, a[i] * suf[i + 1] / suf[i]);
	}
	cout << ans << endl;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃酱斯密酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值