题目链接
题目大意
给两个整数 a , m ( 1 ≤ a < m ≤ 1 0 10 ) a,m (1≤a<m≤10^{10}) a,m(1≤a<m≤1010)有多少个 x x x满足 0 ≤ x < m , g c d ( a , m ) = g c d ( a + x , m ) , 0 ≤ x < m 0≤x<m ,gcd(a,m)=gcd(a+x,m) ,0≤x<m 0≤x<m,gcd(a,m)=gcd(a+x,m),0≤x<m
题目思路
emmm,看到这个题目完全没思路啊,但是仔细分析就能发现解法,首先观察数据
0
<
=
x
<
m
0<=x<m
0<=x<m x的范围正好是m,
gcd(a+x,m)=gcd((a+x)%m,m)则0<=(a+x)%m<m,,然后设p=gcd(a,m)
那么题目变转化成
∑
i
=
0
m
−
1
g
c
d
(
i
,
m
)
=
=
p
\sum_{i=0}^{m-1}{gcd(i,m)==p}
∑i=0m−1gcd(i,m)==p 然后同时除以p 变成了
∑
i
=
0
m
−
1
g
c
d
(
i
p
,
m
p
)
=
=
1
\sum_{i=0}^{m-1}{gcd(\frac{i}{p},\frac{m}{p})==1}
∑i=0m−1gcd(pi,pm)==1
那么结果显然就是
m
p
\frac{m}{p}
pm的欧拉函数
代码
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=1e5+5,mod=998244353;
int t;
ll a,m;
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll euler(ll x){
ll ans=x;
for(ll i=2;i*i<=x;i++){
if(x%i==0){
ans=ans/i*(i-1);
while(x%i==0){
x=x/i;
}
}
}
if(x!=1){
ans=ans/x*(x-1);
}
return ans;
}
signed main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&a,&m);
printf("%lld\n",euler(m/gcd(a,m)));
}
return 0;
}