CodeForces 1459C 数论 GCD

CodeForces 1459C 数论 GCD

原题链接

题意

  • 首先给出n个数

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

思路

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

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

  • 公式:

\[gcd(a, b, c) = gcd(a, b - a, c - b) \]

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

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

\[C = gcd(a_2 - a_1, a_3 - a_2, ···,a_n - a_{n - 1}) \]

之后每次取 \(gcd(C, a_1 + b_j)\)就可以了。注意特判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;
}

posted @ 2021-01-06 16:44  _int_me  阅读(94)  评论(0编辑  收藏  举报