给定两个正整数 a,m,其中 a<m。
请你计算,有多少个小于 m 的非负整数 x 满足:
gcd(a,m)=gcd(a+x,m)
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据占一行,包含两个整数 a,m。
输出格式
每组数据输出一行结果,一个整数,表示满足条件的非负整数 x 的个数。
数据范围
前三个测试点满足,1≤T≤10。
所有测试点满足,1≤T≤50,1≤a<m≤1010。
输入样例:
3
4 9
5 10
42 9999999967
输出样例:
6
1
9999999966
解题思路:
gcd(a,m)== gcd(a+x,m) = d;
由于d为最大公约数所哟 a /= d,x/=d,m/=d后: a+x 与m互质(且x<m)可以转换为a~a+m-1中与m互质的个数。用数轴表述:
(m~a+m-1) % m == (0~a-1) % m;
问题转换为0-m-1中与m互质的个数,又因为0,m-1都与m不互质所以相当于去m的欧拉函数。
欧拉函数:
参考代码:
cpp
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
LL T,a,m;
LL gcd(LL a,LL b)
{
return b ? gcd(b,a % b) : a;
}
LL ula(LL n)
{
LL ans = n;
for(int i=2;i<=n/i;i++)
if(n%i==0)
{
ans = ans / i * (i-1);
while(n%i==0) n/=i;
}
if(n>1) ans = ans / n * (n-1);
return ans;
}
int main()
{
cin>>T;
while(T -- )
{
cin>>a>>m;
m /= gcd(a,m);
cout<<ula(m)<<endl;
}
return 0;
}