题目
求解高次同余方程(k^{x} equiv 1(mod) (m)),不保证(m)为质数
思路
我会扩展BSGS
有个欧拉定理(k^{varphi(m)} equiv 1(mod) (m)),可知答案一定为(varphi(m))的因子
桥豆麻袋,为什么可以使用欧拉定理?说好的(gcd(k,m)=1)才能用呢?
下面证明,该方程有解当且仅当(gcd(k,m)=1)(我比较菜所以写的有点啰嗦啦)
(gcd(k^m,m) | k^m) 又 (gcd(k,m) | gcd(k^m,m))-->(gcd(k,m) | k^x)
此题中((k^x \% m)=1),所以(gcd(k,m) | 1),即(gcd(k,m)=1)
于是(O(sqrt{m}))求出(varphi(m))后再(O(sqrt{varphi(m)}))枚举约数检验就行了
时间复杂度((lognsqrt{n}))
Code
#include<bits/stdc++.h>
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
typedef long long ll;
ll k,mod,phi;
template <class T>
void read(T &x)
{
char c; int sign=1;
while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
}
ll quickpow(ll a,ll b)
{
ll ret=1;
while(b)
{
if(b&1) ret=ret*a%mod;
a=a*a%mod;
b>>=1;
}
return ret;
}
ll gcd(ll a,ll b) { return (!b) ? a : gcd(b,a%b); }
int main()
{
read(mod);read(k);
if(gcd(k,mod)!=1) { puts("Let's go Blue Jays!");return 0; }//无解
phi=mod;
ll p=mod;
for(int i=2;i*i<=p;++i)//求phi(mod)
if(p%i==0)
{
while(p%i==0) p/=i;
phi=phi*(i-1)/i;
}
if(p!=1) phi=phi*(p-1)/p;
ll ans=10000000000000;
for(int i=1;i*i<=phi;++i)
{
if(phi%i) continue;
if(quickpow(k,i)%mod==1) { ans=i; break; }
if(quickpow(k,phi/i)%mod==1) ans=phi/i;
}
cout<<ans<<endl;
return 0;
}