#BSGS,原根,N次剩余,扩欧#洛谷 12694 BZOJ2219 数论之神
分析
幸好模数还是奇数,将其分解为质因数指数幂的形式,它可以通过多个方程进行合并。
而质因数的指数幂的原根一定存在,对 \(X^A\equiv B\pmod {P^C}\) 分类讨论,
如果 \(B\bmod {P^C}==0\) 此时,\(P^{\lceil\frac{C}{A}\rceil+k},k\geq 0\) 都是可行解。
否则如果两者互质就是正常的 BSGS 再在指数上判断是否有解。
而如果不互质还是可以通过方程两边以及模数同时除以公约数进行转化,此时需要判断公约数的次数是否为 \(A\) 的倍数否则无解。
对于这种情况如果令 \(\gcd=P^c\),答案还要乘上 \(P^{c-\frac{c}{A}}\)
代码
#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,prime[MOD],v[MOD],Cnt;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+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 calc(int p,int cnt,int POW){
int mod=POW;
if (m%POW==0) return ksm(p,cnt-((cnt-1)/a+1),mod);
else{
int b=m,_c=0;
while (b%p==0) b/=p,--cnt,++_c,POW/=p;
if (_c%a) return 0;
ToT=0,FJ(phi=POW-POW/p),g=Mn_Rt(POW);
int c=BSGS(g,b,POW),x,y,Gcd=exgcd(a,phi,x,y);
if (c%Gcd) return 0;
else return Gcd*ksm(p,_c-_c/a,mod);
}
}
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){
a=iut(),m=iut(),p=iut()<<1|1,ans=1;
for (int i=1;prime[i]*prime[i]<=p&&ans;++i)
if (p%prime[i]==0){
int _p=1,_c=0;
while (p%prime[i]==0) p/=prime[i],_p*=prime[i],++_c;
ans=ans*calc(prime[i],_c,_p);
}
if (ans&&p>1) ans=ans*calc(p,1,p);
print(ans),putchar(10);
}
return 0;
}

浙公网安备 33010602011771号