1038 X^A Mod P N次剩余(51nod)高次同余 离散对数

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_38772011/article/details/89340768