【51nod 1038】X^A Mod P

题目描述

X^A mod P = B,其中P为质数。给出P和A B,求< P的所有X。
例如:P = 11,A = 3,B = 5。
3^3 Mod 11 = 5
所有数据中,解的数量不超过Sqrt(P)。

分析

这道题包括几个知识点

离散对数(大步小步BSGS算法)

求关于x的同余方程\(y^x \equiv n \pmod{P}(P为质数)\)的解,
\(m=\lceil \sqrt{n} \rceil,x=bm+r\),我们预处理出\(y^i(i\in[0,P-1])\),用map或hash储存起来
我们从小到大枚举b,就可以根据\(y^{(b+1)m} \cdot n^{-1} \equiv y^{m-r}\pmod{P}\),在有序表中找到\(y^{m-r}\)来的到指数r

N次剩余

求关于x的同余方程\(x^y \equiv n \pmod{P}(P为质数)\)的解
设P的原根为g,因为\(\varphi(P)=P-1\),根据原根的性质\(\{1,2,3...P-1\}\)一一与\(\{g^1,g^2,g^3...g^{P-1}\}\)对应
\(x=g^s,n=g^t\)
通过BSGS,我们可以求出t,
于是\(s \cdot y \equiv t \pmod{P-1}\),用扩展欧几里得解借方程。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <bitset>
#include <set>
#include <vector>
const int inf=2147483647;
const int mo=1e6+7;
const int N=100005;
using namespace std;
struct arr{  
    long long x,id;  
    bool operator<(const arr &b)const{  
        if (x == b.x) return id < b.id;  
        return x<b.x;  
    }  
}E[100500]; 
int T;
long long sol[N],P,A,B,G,m,num,ans[N],d[N];
long long ksm(long long x,long long y)
{
    long long s=1;
    for(;y;y>>=1,x=x*x%P)
        if(y&1) s=s*x%P;
    return s;
}
bool check(int G)
{
    int tmp=P-1;
    for(int i=2;i*i<=tmp;i++)
    {
        if(tmp%i) continue;
        if(ksm(G,i)==1 || ksm(G,tmp/i)==1) return false;
    }
    return true;
}
void pre()
{
    for(G=2;!check(G);G++);
    m=ceil(sqrt(P));
    long long v=1;
    for(int i=0;i<=m;i++)
    {
        arr tmp;
        tmp.x=v,tmp.id=i;
        E[i]=tmp;
        v=v*G%P;
    }
    sort(E,E+m);
}
long long BSGS(long long y)
{
    long long ny=ksm(y,P-2),sum=1,s=ksm(G,m);
    for(int i=0;i<m;i++)
    {
        long long val=(sum=sum*s%P)*ny%P;
        arr tmp;
        tmp.x=val,tmp.id=-1;
        long long pos=lower_bound(E,E+m+1,tmp)-E;
        if(E[pos].x==val) return i*m+m-E[pos].id;
    }
    return 0;
}
int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    long long r=exgcd(b,a%b,y,x);
    y-=x*(a/b);
    return r;
}
void residue(long long a,long long b,long long m)
{
    int x=0,y=0,d=exgcd(a,m,x,y);
    if(b%d) return;
    num=d;
    sol[0]=x*(b/d)%m;
    for(int i=1;i<d;i++) sol[i]=(sol[i-1]+m/d)%m;
    for(int i=0;i<d;i++) sol[i]=(sol[i]+m)%m;
}
void solve()
{
    pre();
    num=0,residue(A,BSGS(B),P-1);
    if(!num) printf("No Solution\n");
    else
    {
        for(int i=0;i<num;i++) ans[i]=ksm(G,sol[i]);
        sort(ans,ans+num);
        for(int i=0;i<num;i++) printf("%lld ",ans[i]);
        putchar('\n');
    }
}
int main()
{
    for(scanf("%d",&T);T--;)
    {
        scanf("%lld%lld%lld",&P,&A,&B);
        solve();
    }
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9102565.html