首页 > 其他 > 详细

[洛谷P4861]按钮

时间:2019-10-24 21:12:21      阅读:94      评论:0      收藏:0      [点我收藏+]

题目

求解高次同余方程\(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)})\)枚举约数检验就行了
时间复杂度\((logn\sqrt{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;
}

[洛谷P4861]按钮

原文:https://www.cnblogs.com/Chtholly/p/11734642.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!