• 【解高次同余方程】51nod1038 X^A Mod P


    1038 X^A Mod P 

    基准时间限制:1 秒 空间限制:131072 KB 分值: 320
    X^A mod P = B,其中P为质数。给出P和A B,求< P的所有X。
    例如:P = 11,A = 3,B = 5。
    3^3 Mod 11 = 5
    所有数据中,解的数量不超过Sqrt(P)。
     
    Input
    第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 100)
    第2 - T + 1行:每行3个数P A B,中间用空格隔开。(1 <= A, B < P <= 10^9, P为质数)
    Output
    共T行,每行包括符合条件的X,且0 <= X < P,如果有多个,按照升序排列,中间用空格隔开。如果没有符合条件的X,输出:No Solution。所有数据中,解的数量不超过Sqrt(P)。
    Input示例
    3
    11 3 5
    13 3 1
    13 2 2
    Output示例
    3
    1 3 9
    No Solution

    题解

    解高次同余方程时,先求出来原根

    再用原根代换方程两边(要用到BSGS

    转化成一次剩余问题用EX_GCD求解即可

    P.S. BSGS用map会T,所以我恬不知耻地贴了一份

    代码

    //by 减维
    #include<set>
    #include<map>
    #include<queue>
    #include<ctime>
    #include<cmath>
    #include<bitset>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define il inline
    #define rg register
    #define db double
    #define mpr make_pair
    #define maxn 100005
    #define inf (1<<30)
    #define eps 1e-8
    #define pi 3.1415926535897932384626L
    using namespace std;
    
    inline int read()
    {
        int ret=0;bool fla=0;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-'){fla=1;ch=getchar();}
        while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
        return fla?-ret:ret;
    }
    
    int t,num,cnt;
    ll a,p,b,g,phip,pri[maxn],ans[maxn];
    vector<ll> phipri;
    map<ll,ll> mp;
    bool pd[maxn];
    
    il ll ksm(ll x,ll y,ll mod)
    {
        ll ret=1;x%=mod;
        for(;y;y>>=1,x=x*x%mod)
            if(y&1) ret=ret*x%mod;
        return ret;
    }
    
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(b==0){x=1;y=0;return a;}
        ll gcd=exgcd(b,a%b,y,x);
        y-=a/b*x;
        return gcd;
    }
    
    il void pre()
    {
        for(int i=2;i<=maxn-5;++i)
        {
            if(!pd[i]) pri[++num]=i;
            for(int j=1;j<=num&&i*pri[j]<=maxn-5;++j)
            {
                pd[i*pri[j]]=1;
                if(i%pri[j]==0) break;
            }
        }
    }
    
    il ll getphi(ll x)
    {
        ll ret=x;
        for(int i=1;pri[i]*pri[i]<=x;++i)
            if(x%pri[i]==0)
            {
                ret=ret/pri[i]*(pri[i]-1);
                while(x%pri[i]==0) x/=pri[i];
            }
        if(x>1) ret=ret/x*(x-1);
        return ret;
    }
    
    il bool check(ll g,ll x,ll p)
    {
        int siz=phipri.size();
        for(int i=0;i<siz;++i)
            if(ksm(g,x/phipri[i],p)==1) return 0;
        return 1;
    }
    
    il ll getg(ll x,ll p)
    {
        ll tmp=x;
        phipri.clear();
        for(int i=2;i*i<=x;++i)
            if(x%i==0)
            {
                phipri.push_back(i);//printf("%lld ",pri[i]);
                while(x%i==0) x/=i;
            }
        if(x!=1) phipri.push_back(x);//,printf("%lld ",x);
        //puts("");
        x=tmp;
        ll gen=1;
        while(1)
        {
            if(check(gen,x,p)) return gen;
            gen++;
        }
    }
    
    struct sa{
        long long x;
        int id;
        bool operator<(const sa &b)const{
            if (x == b.x) return id < b.id;
            return x<b.x;
        }
    }rec[100500];
    //用rec存离散对数
    long long bsgs(long long x,long long n,long long m){
        int s=(int)(sqrt((double)m+0.5));
        while((long long)s*s<=m)s++;
        long long cur=1;
        sa tmp;
        for(int i=0;i<s;i++){
            tmp.x=cur,tmp.id=i;
            rec[i]=tmp;
            cur=cur*x%m;
        }
        sort(rec,rec+s);
        //这里不能用map查找比较慢,采用排序二分就快了
        long long mul= ksm(cur, m - 2, m) % m;
        //这里有的方法是在下面的循环里求解快速幂,但本题是不行的  要在循环外面弄,保证时间
        cur=1;
    
        for(long long i=0;i<s;i++){
            long long more=n*cur%m;
            tmp.x=more,tmp.id=-1;
            int j=lower_bound(rec,rec+s,tmp)-rec;
            if(rec[j].x==more){
                return i*s+rec[j].id;
            }
            cur=cur*mul%m;
        }
        return -1;
    }
    
    int main()
    {
        t=read();
        pre();
        while(t--){
            p=read(),a=read(),b=read();
            phip=p-1;cnt=0;
            g=getg(phip,p);
            //printf("%lld ",g);
            ll c=bsgs(g,b,p);
            //printf("%lld ",c);
            if(c==-1){puts("No Solution");continue;}
            ll x,y;
            ll gcd=exgcd(a,phip,x,y);
            //printf("%lld ",gcd);
            if(c%gcd!=0){puts("No Solution");continue;}
            x=x*(c/gcd)%phip;
            ll delt=phip/gcd;
            for(int i=0;i<gcd;++i)
            {
                x=((x+delt)%phip+phip)%phip;
                ans[++cnt]=ksm(g,x,p);
            }
            sort(ans+1,ans+cnt+1);
            for(int i=1;i<=cnt;++i) printf("%lld ",ans[i]);puts("");
        }
        return 0;
    }
  • 相关阅读:
    ComponentOne Studio Enterprise ———C1控件barchat 的统计图格式 设置
    OpenStack开发学习笔记04————
    短信推送API接口实现---------阿里大于
    OpenStack开发学习笔记03————创建一个openstack
    OpenStack开发学习笔记02————环境的安装和部署
    OpenStack开发学习笔记01
    MVC模式在Java Web应用程序中的实例分析
    javascript的setTimeout以及setInterval休眠问题。
    BFC 神奇背后的原理
    jquery checkBox的问题
  • 原文地址:https://www.cnblogs.com/rir1715/p/8584029.html
Copyright © 2020-2023  润新知