CodeForces 1459C 数论 GCD

博客详细介绍了CodeForces 1459C 数论 GCD问题的解决过程。首先,博主解释了题目要求计算n个数在不断加入新的数后的总体GCD。接着,博主提出由于n和m的数量级较大,需要采用近似线性的算法。通过分析gcd的性质,得出gcd(a, b, c) = gcd(a, b - a, c - b)的结论,并对初始数组进行排序。博主给出的解决方案是先计算第一列数的特定gcd,然后在每次询问时,结合新加入的数与之前的结果计算gcd。最后,博主提到了针对特殊情况的处理,例如数组中只有一个元素的情况。" 110371194,10295944,Python播放音频指南,"['Python', '音频处理', '播放音频', '多媒体开发', 'pydub']

CodeForces 1459C 数论 GCD

原题链接

题意
  • 首先给出n个数

  • 之后给出m个数,每次问之前的n个数加上当前的这个数之后,总体的gcd是多少,也就是答案需要求出m个总体的gcd

思路
  • 因为n和m都是2e5的范围,所以必须使用接近线性的算法

  • 考虑每次的计算前都是对原数组进行加法运算的改动,所以可以去思考gcd计算中和加减法有关的知识。也就是更相减损术

  • 公式:

g c d ( a , b , c ) = g c d ( a , b − a , c − b ) gcd(a, b, c) = gcd(a, b - a, c - b) gcd(a,b,c)=gcd(a,ba,cb)

对三个以上的序列也同样成立

  • 所以先将第一列数进行从小到大的排序,然后计算出

C = g c d ( a 2 − a 1 , a 3 − a 2 , ⋅ ⋅ ⋅ , a n − a n − 1 ) C = gcd(a_2 - a_1, a_3 - a_2, ···,a_n - a_{n - 1}) C=gcd(a2a1,a3a2,,anan1)

之后每次取 g c d ( C , a 1 + b j ) gcd(C, a_1 + b_j) gcd(C,a1+bj)就可以了。注意特判a数组中只有一个的情形。

AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

long long gcdd(long long a, long long b)
{
	if (!b)
	{
		return a;
	}
	else
	{
		return gcdd(b, a % b);
	}
}

int n, m;
long long aa[200005];
long long bb[200005];

int main()
{
	cin >> n >> m;
	long long gd;
	for (int i = 1; i <= n; ++i)
	{
		scanf("%lld", &aa[i]);
	}
	sort(aa + 1, aa + n + 1);
	int co = 0;
	bb[0] = 0;
	bb[++co] = aa[1];
	for (int i = 2; i <= n; ++i)//去重 
	{
		if (aa[i] != aa[i - 1])
		{
			bb[++co] = aa[i];
		}
	}
	gd = bb[co] - bb[co - 1];
	for (int i = co - 1; i >= 2; --i)
	{
		gd = gcdd(gd, bb[i] - bb[i - 1]);
	}
	for (int i = 1; i <= m; ++i)
	{
		long long xx;
		scanf("%lld", &xx);
		printf("%lld ", co == 1 ? xx + bb[1] : gcdd(gd, bb[1] + xx));
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值