Codeforces 1295D Same GCDs

Description

描述

给出 $a$,$m$,求出 $0 le x < m$ 中,$gcd(a + x, m) = gcd(a, m)$ 的个数。

输入

第一行一个正整数 $T$($1 le T le 50$),表示数据组数。

接下来 $T$ 行,每行两个正整数 $a$ 和 $m$($1 le a, m le 10^{10}$)。

输出

每组数据一个数表示答案。

样例

输入

3
4 9
5 10
42 9999999967

输出

6
1
9999999966

解释

第一组数据:$x = 0, 1, 3, 4, 6, 7$ 可行。

第二组数据:$x = 0$ 可行。

Solution

题目是让我们求这个式子:

$$ sum_{x = 0}^{m - 1} [gcd(a, m) = gcd(a + x, m)] $$

然后,根据辗转相除法,我们可以把它转化为:

$$ sum_{x = 0}^{m - 1} [gcd(a, m) = gcd((a + x) mod m, m)] $$

右边就是把 $[0, m)$ 的区间向右平移了 $a$ 个单位,取模了以后显然还是 $[0, m)$ 的区间。

于是:

$$sum_{i = 0}^{m -1} [gcd(i, m) = gcd(a, m)]$$

令 $g = gcd(a, m)$,就是求:

$$sum_{i = 0}^{m-1} [gcd(i, m) = g]$$
$$ sum_{0 le i <m}^{g|i}left[ gcdleft(dfrac i g , dfrac m g ight) = 1 ight]$$

然后,左边的就是 $left[1 , dfrac m g ight)$ 的一段数,所以,这个就是:

$$ sum_{i = 1}^{frac m g - 1} left[gcd left(i, dfrac m g ight) = 1 ight] $$

然后这个就是 $varphileft(dfrac m g ight) = varphileft(dfrac m {gcd(a, m)} ight)$ 了。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL gcd(LL a, LL b) { if(!b) return a; return gcd(b, a % b); }
LL phi(LL x)
{
	LL res = 1;
	for(LL i = 2; i * i <= x; i++)
	{
		if(x % i) continue;
		res *= i - 1; x /= i;
		while(x % i == 0) res *= i, x /= i;
	}
	if(x > 1) res *= x - 1;
	return res;
}
int main()
{
	ios::sync_with_stdio(false);
	LL T;
	cin >> T;
	while(T--)
	{
		LL a, m;
		cin >> a >> m;
		cout << phi(m / gcd(a, m)) << endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/syksykCCC/p/CF1295D.html