#原根,BSGS,扩欧#51nod 1038 X^A Mod P
作者:互联网
题目
\(T(T\leq 100)\) 组询问在模 \(P\) 意义下给 \(B\) 开 \(A\) 次方根,
求出 \([0,P)\) 的所有解,\(P\) 是一个质数。
分析
求出 \(P\) 的原根 \(G\),若 \(G^x\equiv B\pmod{P}\),这个 \(x\) 可以通过 BSGS 求出来。
那么 \(X^A\equiv B\pmod{P}\) 就可以转换成 \(G^{kA}\equiv G^x\pmod{P}\)
其中 \(G^k\equiv X\pmod{P}\),那么 \(kA\equiv x\pmod{P-1}\)
用扩欧求出来 \(k\) 的所有解再带进去 \(G^k\) 算出所有的 \(X\)
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD=70001;
struct Linked_Hash{
struct node{int y,w,next;}E[MOD]; int Et,hs[MOD];
void Clear(){Et=0,memset(hs,-1,sizeof(hs));}
void Insert(int w,int x){E[++Et]=(node){x,w,hs[w%MOD]},hs[w%MOD]=Et;}
int locate(int W){
for (int i=hs[W%MOD];~i;i=E[i].next)
if (E[i].w==W) return E[i].y;
return -1;
}
}ha;
int p,phi,P[MOD],ToT,g,a,m,ans[MOD],tot,prime[MOD],v[MOD],Cnt;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
void FJ(int p){
for (int i=1;prime[i]*prime[i]<=p;++i)
if (p%prime[i]==0){
P[++ToT]=prime[i];
while (p%prime[i]==0) p/=prime[i];
}
if (p>1) P[++ToT]=p;
}
int ksm(int x,int y,int p){
int ans=1;
for (;y;y>>=1,x=1ll*x*x%p)
if (y&1) ans=1ll*ans*x%p;
return ans;
}
bool check(int x,int p){
if (ksm(x,phi,p)!=1) return 0;
for (int i=1;i<=ToT;++i)
if (ksm(x,phi/P[i],p)==1) return 0;
return 1;
}
int Mn_Rt(int p){
for (int i=1;i<p;++i)
if (check(i,p)) return i;
return -1;
}
int BSGS(int a,int b,int mod){
ha.Clear();
int ir=sqrt(mod)+1,now=1;
for (int i=0;i<ir;++i)
ha.Insert(1ll*now*b%mod,i),now=1ll*now*a%mod;
a=now,now=1;
if (!a) return !b?1:-1;
for (int i=0;i<=ir;++i){
int j=ha.locate(now);
if (j>=0&&i*ir>=j) return i*ir-j;
now=1ll*now*a%mod;
}
return -1;
}
int exgcd(int a,int b,int &x,int &y){
if (!b) {x=1,y=0; return a;}
int Gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return Gcd;
}
int main(){
for (int i=2;i<MOD;++i){
if (!v[i]) prime[++Cnt]=i;
for (int j=1;j<=Cnt&&prime[j]<=MOD/i;++j){
v[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
for (int Test=iut();Test;--Test){
ToT=tot=0,p=iut(),a=iut(),m=iut(),FJ(phi=p-1),g=Mn_Rt(p);
int b=phi,x,y,c=BSGS(g,m,p),Gcd=exgcd(a,b,x,y);
if (c%Gcd) printf("No Solution\n");
else{
x=(1ll*x*(c/Gcd)%phi+phi)%phi;
for (int i=1;i<=Gcd;++i)
x=(x+b/Gcd)%phi,ans[++tot]=ksm(g,x,p);
sort(ans+1,ans+1+tot),tot=unique(ans+1,ans+1+tot)-ans-1;
for (int i=1;i<=tot;++i) print(ans[i]),putchar(i==tot?10:32);
}
}
return 0;
}
标签:return,原根,51nod,hs,int,1038,ans,equiv,MOD 来源: https://www.cnblogs.com/Spare-No-Effort/p/15911224.html