luogu P4861 【按钮】

首先根据题意可以看出题目要求的是

\[K^x \equiv 1 \ (mod\ M) \]

\(x\)的最小正整数解。

如果$\ gcd(M,K)=1\ $则有解。

然后,根据欧拉定理,得到

\[K^{\phi(M)}\equiv 1 \ (mod\ M) \]

\(\phi(M)\)并不一定是\(x\)的最小整数解。

可以猜到\(x|\phi(M)\)。证明别的题解有讲,这里不多说。

所以可以枚举\(\phi(M)\)的约数,找到最小的\(x\)满足

\[K^x\equiv1\ (mod\ M)\ ,\ x|\phi(M) \]

\(\phi(M)\)用这个式子算

\[M=\prod_{i=1}^{n} p_i^{c_i} \]

\[\phi(M)=M \prod_{i=1}^{n}\frac{p_i-1}{p_i} \]

就做完了。

\(Code:\)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define int long long
#define _min(a,b) ((a)<(b)?(a):(b)) 
inline int read(){
	register int x=0,f=0,ch=getchar();
	while('0'>ch||ch>'9')f^=ch=='-',ch=getchar();
	while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
	return f?-x:x;
}
int res,phi;
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
inline void Gphi(int x){//找phi
	phi=x;
	for(register int i=2;i*i<=x;++i){
		if(x%i==0){
			phi=phi/i*(i-1);
			while(x%i==0)x/=i;
		}
	}
	if(x>1)phi=phi/x*(x-1);
}
inline int qpow(int x,int p,int P){//快速幂
	res=1;
	for(;p;p>>=1,x=x*x%P)if(p&1)res=res*x%P;
	return res%P;
}
#define INF 0x3f3f3f3f3f3f3f3f
int m,k,ans=INF;
inline int Gans(int x){//枚举约数找答案
	for(register int i=1;i*i<=x;++i){
		if(x%i==0){
        //这里显然 i<=x/i,因为我们枚举的i满足i<=sqrt(x)的,所以当i有解时,不用判断x/i的答案
			if(qpow(k,i,m)%m==1)ans=_min(ans,i);
			else if(qpow(k,x/i,m)%m==1)ans=_min(ans,x/i);
		}
	}
	return ans;
}
signed main(){
	m=read(),k=read();
	if(gcd(m,k)==1){
		Gphi(m);
		printf("%lld\n",Gans(phi));
	}else printf("Let's go Blue Jays!\n");
	return 0;
}

笔者比较菜,有什么问题私信,谢谢

posted @ 2020-03-19 18:05  Lates  阅读(224)  评论(0)    收藏  举报