题目链接:CF1295D Same GCDs
本文版权归博客园和蒟蒻wjr所有,欢迎转载,但需保留此段声明,并给出原文链接,如有侵权行为,还请不吝啬向博主举报,谢谢合作。
[description
]
给定(a,m),求出有多少个(x)满足(0leq x<m)且
[gcd(a,m)=gcd(a+x,m)
]
(gcd(x,y))表示(x)和(y)的最大公因数
[solution
]
数论题
考虑设(d=gcd(a,m))
肯定满足(d|a,d|m,d|(a+x))
( herefore d|x)
结论1:
[gcd(frac{a+x}{d},frac{m}{d})=1
]
证明:
假设(gcd(frac{a+x}{d},frac{m}{d}) eq 1)
即(gcd(frac{a+x}{d},frac{m}{d})> 1)
此时
[gcd(a+x,m)=gcd(frac{a+x}{d} imes d,frac{m}{d} imes d)>d
]
即(gcd(a+x,m) eq gcd(a,m))
互相矛盾
综上所述:(gcd(frac{a+x}{d},frac{m}{d})=1)成立
结论2:
答案是
[varphi(frac{m}{d})
]
显然对与任意与m互质的数(p)和任意正整数(k)
满足:
[gcd(p+frac {km}{d},frac{m}{d})=gcd((p+kfrac{m}{d}) mod frac{m}{d},frac{m}{d})=gcd(p,frac{m}{d})=1
]
显然(p+frac {km}{d})与(frac{m}{d})互质
对于当(a+xleq m),答案是(frac{a}{d}leq xleq frac{m}{d})的与(frac{m}{d})互质的个数
对于与(m<a+x<a+m),答案是(x<frac{a}{d})的与(frac{m}{d})互质的个数
两个答案区间合并即是(varphi(frac{m}{d}))
欧拉函数:
其中(p_1, p_2……p_k)为(n)的所有质因数,(n)是不为(0)的整数。(varphi(1)=1)(唯一和(1)互质的数就是(1)本身)。
[varphi(n)=nprod _ {i=1}^{k}(1-frac{1}{p_i})
]
因为n最多有一个大于(sqrt{n})的质因数
所以可以得到以下代码
inline long long Eular(long long n)
{
long long ans=n;
for(re int i=2; 1ll*i*i<= n; i++)
{
if(n%i==0)
{
ans-=ans/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
ans-=ans/n;
return ans;
}
欧拉函数复杂度(O(sqrt n))
算法总复杂度(O(Tsqrt n))
[code
]
#include<cstdio>
#define re register
#define ll long long
using namespace std;
template<typename T>
inline void read(T&x)
{
x=0;
char s=(char)getchar();
bool flag=false;
while(!(s>='0'&&s<='9'))
{
if(s=='-')
flag=true;
s=(char)getchar();
}
while(s>='0'&&s<='9')
{
x=(x<<1)+(x<<3)+s-'0';
s=(char)getchar();
}
if(flag)
x=(~x)+1;
return;
}
inline ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
inline long long Eular(long long n)
{
long long ans=n;
for(re int i=2; 1ll*i*i<= n; i++)
{
if(n%i==0)
{
ans-=ans/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
ans-=ans/n;
return ans;
}
int T;
int main()
{
read(T);
while(T--)
{
ll a,m;
read(a),read(m);
printf("%lld
",Eular(m/gcd(a,m)));
}
return 0;
}