題目鏈接:CF1295D Same GCDs
本文版權歸博客園和蒟蒻wjr所有,歡迎轉載,但需保留此段聲明,並給出原文鏈接,如有侵權行為,還請不吝嗇向博主舉報,謝謝合作。
給定\(a,m\),求出有多少個\(x\)滿足\(0\leq x<m\)且
\(gcd(x,y)\)表示\(x\)和\(y\)的最大公因數
數論題
考慮設\(d=gcd(a,m)\)
肯定滿足\(d|a,d|m,d|(a+x)\)
\(\therefore d|x\)
結論1:
證明:
假設\(gcd(\frac{a+x}{d},\frac{m}{d})\neq 1\)
即\(gcd(\frac{a+x}{d},\frac{m}{d})> 1\)
此時
即\(gcd(a+x,m)\neq gcd(a,m)\)
互相矛盾
綜上所述:\(gcd(\frac{a+x}{d},\frac{m}{d})=1\)成立
結論2:
答案是
顯然對與任意與m互質的數\(p\)和任意正整數\(k\)
滿足:
顯然\(p+\frac {km}{d}\)與\(\frac{m}{d}\)互質
對於當\(a+x\leq m\),答案是\(\frac{a}{d}\leq x\leq \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\)本身)。
因為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(T\sqrt n)\)
#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\n",Eular(m/gcd(a,m)));
}
return 0;
}