题目大意

给你一个n,求最小正整数k,使得对于任意整数a都满足
anka(mod n)
或输出无解。

做法

首先发现n含有平方因子时是无解的。
假设n含有平方因子pc,那么我们令a=npcp时是不合法的。
因为nkn2cc,因此ank显然模n为0,而显然an不为0
考虑中国剩余定理,因此对于n每个质因子p都要有anka(mod p)
ap的倍数显然成立,这里只考虑(a,p)=1
ank11(mod p)
接下来我们可以证明p1|nk1
因为p是质数,一定存在原根g
如果a=g,显然p1|nk1
否则设a=gc,显然c不为0。有c(nk1)0(mod p1)
显然也有p1|nk1
因此我们现在求出所有p1的最小公倍数,记为lcm,那么lcm|nk1
因此nk1(mod lcm)
如果(n,lcm)不为1显然无解,否则肯定有解,因为ϕ(lcm)就是可行解。
ϕ(lcm)分解质因数,枚举一个质因数并代入检验,即可得到最小k

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll p[1000];
int c[1000];
ll n,phi,k;
int i,tot,top;
ll random(ll x){
    ll t=rand()%10000;
    t=t*10000+rand()%10000;
    t=t*10000+rand()%10000;
    t=t*10000+rand()%10000;
    return t%x;
}
ll mul(ll a,ll b,ll p){
    ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
    return tmp<0?tmp+p:(tmp>=p?tmp-p:tmp);
}
ll qsm(ll x,ll y,ll mo){
    if (!y) return 1;
    ll t=qsm(x,y/2,mo);
    t=mul(t,t,mo);
    if (y%2) t=mul(t,x,mo);
    return t;
}
bool Miller_Rabin(ll n){
    if (n==1) return 0;
    int s=10,t=0,i;
    ll a,p,k=n-1;
    while (k%2==0) k/=2,t++;
    while (s--){
        a=random(n-1)+1;
        p=a=qsm(a,k,n);
        fo(i,1,t){
            a=mul(a,a,n);
            if (a==1&&p!=1&&p!=n-1) return 0;
            p=a;
        }
        if (a!=1) return 0;
    }
    return 1;
}
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll Pollard_Rho(ll n){
    ll k,x,y,c,d,i=1;
    while (1){
        c=random(n-1);
        k=2;y=x=random(n);
        i=1;
        while (1){
            y=(mul(y,y,n)+c)%n;
            d=gcd(abs(x-y),n);
            if (i==k) x=y,k<<=1;
            i++;
            if (d!=1) break;
        }
        if (d!=n) return d;
    }
}
void work(ll n){
    if (Miller_Rabin(n)){
        p[++top]=n;
        return;
    }
    ll p=Pollard_Rho(n);
    ll q=n/p;
    work(p);work(q);
}
void dfs(int x,ll y){
    if (y>=k) return;
    if (x==top+1){
        ll t=qsm(n,y,phi);
        (t+=phi)%=phi;
        if (t==1) k=y;
        return;
    }
    int i;
    ll t=1;
    fo(i,0,c[x]){
        dfs(x+1,y*t);
        t=t*p[x];
    }
}
int main(){
    freopen("pow.in","r",stdin);freopen("pow.out","w",stdout);
    scanf("%lld",&n);
    work(n);
    sort(p+1,p+top+1);
    phi=1;
    fo(i,1,top){
        phi=phi*(p[i]-1)/gcd(phi,p[i]-1);
        if (p[i]==p[i-1]){
            printf("-1\n");
            return 0;
        }
    }
    if (gcd(phi,n)!=1){
        printf("-1\n");
        return 0;
    }
    if (phi==1){
        printf("1\n");
        return 0;
    }
    top=0;
    work(phi);
    sort(p+1,p+top+1);
    k=1;
    fo(i,1,top){
        if (p[i]==p[i-1]) k=k*p[i];
        else k=k*(p[i]-1);
    }
    if (k==1){
        printf("1\n");
        return 0;
    }
    top=0;
    work(k);
    sort(p+1,p+top+1);
    tot=top;
    top=0;
    fo(i,1,tot){
        if (p[i]!=p[i-1]){
            top++;
            p[top]=p[i];
            c[top]=1;
        }
        else c[top]++;
    }
    dfs(1,1);
    printf("%lld\n",k);
}
阅读更多
版权声明:本文是蒟蒻写出来的,神犇转载也要说一声哦! https://blog.csdn.net/WerKeyTom_FTD/article/details/80464959
上一篇[UER#6 C]逃跑
下一篇小Y增员操直播群
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭