版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38772011/article/details/89340768
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:
3
11 3 5
13 3 1
13 2 2
output:
3 1 3 9 No Solution
解:
g为p的原根,p为素数,所以phi(p)=p-1。
原根的性质得:如果g为p的原根,则:g^i mod p != g^j mod p (p为素数),
其中i != j且i, j介於1至(p-1)之间
所以,可以设g^y=x, g^t=a,则有:
g^(y*N)%p=g^t
又由原根的性质:
g^(y*N)%p=g^t -> (y*N)%(p-1)=t (拓展欧几里得解)
另外g^t=a可以由离散对数求出
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100005;
bool pd[maxn];
ll pri[maxn],ans[maxn];;
vector<ll> phipri;
map<ll,ll> mp;
int t,num,cnt;
ll p,a,b,g,phip;
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;
}
}
}
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;
}
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;
}
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);
while(x%i==0) x/=i;
}
if(x!=1) phipri.push_back(x);
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];
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);
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() {
cin>>t;
pre();
while(t--) {
cin>>p>>a>>b;
phip = p-1;
cnt = 0;
g = getg(phip,p);
// cout<<g<<endl;
ll c = bsgs(g,b,p);
// cout<<c<<endl;
if(c==-1){puts("No Solution");continue;}
ll x,y;
ll gcd=exgcd(a,phip,x,y);
// printf("%lld ",gcd);
// cout<<x<<" "<<y<<endl;
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;
}