题目描述
X^A mod P = B,其中P为质数。给出P和A B,求< P的全部X。 例如:P = 11,A = 3,B = 5。 3^3 Mod 11 = 5 全部数据中,解的数量不超过Sqrt(P)。ios
分析
这道题包括几个知识点算法
离散对数(大步小步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}$来的到指数rui
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}$,用扩展欧几里得解方程。spa
#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(); } }