题意:给定两个整数a和m,计算有多少个x(0 <= x < m)使得gcd(a, m) == gcd(a + x, m)

分析:互质的定义是\(gcd(a, b) == 1\),即a和b之间的公约数只有1,由欧几里得算法,我们可以得到,gcd(a, m) == gcd(m, a % m),那么 gcd(a + x, m) == gcd(m, (a + x) % m),取模完使得a + x的区间落在[0, m)之间,我们可以得到gcd((a + x) % m, m) == gcd(a, m),我们假设(a + x) % m == i,gcd(a, m) == d,那么即要求\(\sum\limits_{i = 0}^{m - 1}(gcd(i, m)) == d\) ,然后我们再求\(\sum\limits_{i = 0}^{m - 1}(gcd(\frac{i}{d}, \frac{m}{d})) == 1\),即求 [0, m - 1]这个区间中与m / d互质的个数有多少个,这样,我们就可以通过欧拉函数求出这个答案,欧拉函数可以求出1~N中与N互质的个数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
using LL = long long;
LL gcd(LL a, LL b)
{
	return b ? gcd(b, a % b) : a;
}

LL phi(LL x)
{
	LL res = x;
	for (int i = 2; i <= x / i; ++i)
	{
		if (x % i == 0)
		{
			res = res / i * (i - 1);
			while (x % i == 0) x /= i;
		}
	}
	if (x > 1) res = res / x * (x - 1);
	return res;
}
int main()
{
	int t;
	cin >> t;

	while (t--)
	{
		LL a, m;
		cin >> a >> m;
		LL d = gcd(a, m);

		cout << phi(m / d) << endl;
	}


	return 0;
}