CF1295D Same GCDs


我的blog

題目鏈接:CF1295D Same GCDs

本文版權歸博客園和蒟蒻wjr所有,歡迎轉載,但需保留此段聲明,並給出原文鏈接,如有侵權行為,還請不吝嗇向博主舉報,謝謝合作。

\[description \]

給定\(a,m\),求出有多少個\(x\)滿足\(0\leq 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)\)

\(\therefore d|x\)

結論1:

\[gcd(\frac{a+x}{d},\frac{m}{d})=1 \]

證明:

假設\(gcd(\frac{a+x}{d},\frac{m}{d})\neq 1\)

\(gcd(\frac{a+x}{d},\frac{m}{d})> 1\)

此時

\[gcd(a+x,m)=gcd(\frac{a+x}{d}\times d,\frac{m}{d}\times d)>d \]

\(gcd(a+x,m)\neq 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+k\frac{m}{d})\ mod\ \frac{m}{d},\frac{m}{d})=gcd(p,\frac{m}{d})=1 \]

顯然\(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\)本身)。

\[\varphi(n)=n\prod _ {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(T\sqrt 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\n",Eular(m/gcd(a,m)));
	}
 
	return 0;
}




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM