YY模拟:幂(CRT+Pollard-Rho)

题意:
给定 n n ,求最小正整数k,使得任意 a a 满足anka(modn),无解输出 1 − 1
n1e18 n ≤ 1 e 18

题解:
首先若 n n 含平方质因子p,那么令 k=p k = p ,结果一定是 p2 p 2 的倍数, 无解。

否则根据CRT得到 log log 个同余方程: anka(modp) a n k ≡ a ( mod p )
p=2 p = 2 则一定成立,否则有: nk1(modp1) n k ≡ 1 ( mod p − 1 ) ,首先要满足 n(p1) n ⊥ ( p − 1 ) ,根据欧拉定理 nφ(a)1(moda) n φ ( a ) ≡ 1 ( mod a ) ,得知 k k 一定为φ(p1)的因数。 我们用试除法即可。

最后的答案为所有 k k <script type="math/tex" id="MathJax-Element-152">k</script>的lcm。

#include <bits/stdc++.h>
using namespace std;
typedef __int128 IL;
typedef long long LL;
typedef long double LD;
typedef unsigned int UINT;
inline LL mul(LL x,LL y,LL mod) {return (LL)((IL)x*y%mod);}
inline LL power(LL a,LL b,LL mod,LL rs=1) {for(;b;b>>=1,a=mul(a,a,mod)) if(b&1) rs=mul(rs,a,mod);return rs;}
inline LL gcd(LL x,LL y) {return (y ? gcd(y,x%y) : x);}
namespace RHO {
    vector <LL> *fac;

    inline UINT unit() {
        static UINT state0=19260817;
        state0^=(state0<<13);
        state0^=(state0>>17);
        state0^=(state0<<5);
        return state0;
    }

    const int ai[11]={0,2,3,5,7,11,13,17,19,23,29};
    inline LL rho(LL n,LL c) {
        LL x=unit()%n+1, y=x;
        for(int k=2,i=1;;++i) {
            x=(mul(x,x,n)+c)%n;
            LL p=gcd(n,abs(x-y));
            if(p!=1) return p;
            (i==k) && (k<<=1, y=x);
        }
    }
    inline bool check(LL n,LL v,LL s1,LL s2) {
        v=power(v,s1,n); LL p=v;
        for(int i=1;i<=s2;i++) {
            v=mul(p,p,n);
            if(v==1 && (p!=1 && p!=n-1)) return 0;
            p=v;
        }
        if(p!=1) return 0;
        return 1;
    }
    inline bool MR(LL n) {
        if(n==2) return 1;
        if(!(n%2)) return 0;
        if(n==3) return 1;
        if((n%6!=1) && (n%6!=5)) return 0;
        LL s1=n-1, s2=0;
        while(!(s1%2)) s1>>=1, ++s2;
        for(int i=1;i<=10;i++) {
            if(ai[i]==n) return 1;
            if(!(n%ai[i])) return 0;    
            if(!check(n,ai[i],s1,s2)) return 0;
        }
        return 1;
    }
    inline void solve(LL n) {
        if(MR(n)) {fac->push_back(n); return;}
        else {
            LL d=rho(n,unit()%n);
            while(d==n) d=rho(n,unit()%n);
            solve(d); solve(n/d);
        }
    } 
    inline void getfac(LL n,vector <LL> &factor) {
        fac=&factor; fac->clear(); 
        solve(n);
    }
    inline LL getphi(LL p) {
        vector <LL> factor;
        getfac(p,factor);
        sort(factor.begin(),factor.end());
        factor.erase(unique(factor.begin(),factor.end()),factor.end());
        LL rs=p;
        for(int i=0;i<factor.size();++i) rs=rs/factor[i]*(factor[i]-1);
        return rs;
    }
} 
LL n; 
inline LL solve(LL p) {
    vector <LL> fac; 
    LL rs=p-1;
    if(gcd(n,rs)!=1) {puts("-1"); exit(0); }
    rs=RHO::getphi(rs);
    if(rs==1) return 1;
    RHO::getfac(rs,fac);
    for(int i=0;i<fac.size();++i) {
        LL tp=rs/fac[i];
        if(power(n,tp,p-1)==1) rs=tp;
    }
    return rs;
}
int main() {
    cin>>n;  vector <LL> fac;
    RHO::getfac(n,fac);
    int sze=fac.size();
    sort(fac.begin(),fac.end());
    fac.erase(unique(fac.begin(),fac.end()),fac.end());
    if(fac.size()!=sze) {puts("-1"); return 0;}
    LL k=1;
    for(int i=0;i<sze;++i) {
        LL p=fac[i]; if(p==2) continue;
        LL k2=solve(p);
        k=k/gcd(k,k2)*k2;
    }
    cout<<k<<endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值