题意:给定两个整数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,那么即要求(sumlimits_{i = 0}^{m - 1}(gcd(i, m)) == d) ,然后我们再求(sumlimits_{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;
}