Codeforces 1295 D. Same GCDs
题意:
给定两个整数(a,mleq10^{10})。
问有多少个(0leq x<m)有(gcd(a,m)=gcd(a+x,m))。
思路:
把结果写成表达式
[sum_{x=0}^{m-1}[gcd(a,m)=gcd(a+x,m)]
]
根据gcd的计算过程有:
[sum_{x=0}^{m-1}[gcd(a,m)=gcd((a+x)mod m, m)]
]
我们知道(x)的取值范围在([0,m-1]),其实就是相当于把(a)在数轴上向右平移了这么多个单位,取模之后又回到了([0,m-1])的区间。
所以有
[sum_{i=0}^{m-1}[gcd(i,m)=gcd(a,m)]
]
提取(gcd(a,m)=d)。
[sum_{i=0}^{m-1}[gcd(i,m)=g]\sum_{0leq i<m}^{g|i}[gcd(frac{i}{g},frac{m}{g})=1]
]
这个就是(varphi(frac{m}{g}))。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, m;
ll phi(ll x)
{
ll res = x;
for(ll 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;
}
ll gcd(ll a, ll b){
if(b == 0) return a;
return gcd(b, a%b);
}
void solve()
{
cin >> a >> m;
ll k = gcd(a, m);
cout << phi(m/k) << endl;
}
int main()
{
int T; scanf("%d", &T);
while(T--) solve();
}