版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/80626959
好板永流传
1、给定 ,计算 的值;
2、给定 ,计算满足 的最小非负整数x;
3、给定 ,计算满足 的最小非负整数x。
操作1快速幂
操作2扩展欧几里得算法
操作三BSGS
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cmath>
#define ll long long
using namespace std;
map<ll,ll> mp;
ll ksm(ll q,ll w,ll p)
{
ll h=1;
while(w)
{
if(w&1)
h=h*q%p;
q=q*q%p;
w>>=1;
}
return h;
}
ll x,y,ans;
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
return;
}
ll gcd(ll a,ll b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
int t,k;
int main()
{
cin>>t>>k;
if(k==1)
{
ll yy,zz,pp;
for(int i=1;i<=t;++i)
{
scanf("%lld%lld%lld",&yy,&zz,&pp);
printf("%lld\n",ksm(yy,zz,pp));
}
}
if(k==2)
{
ll yy,zz,pp;
for(int i=1;i<=t;++i)
{
scanf("%lld%lld%lld",&yy,&zz,&pp);
ll b=pp;
ll g=gcd(yy,pp);
if(zz%g!=0)
{
printf("Orz, I cannot find x!\n");
continue;
}
yy/=g,pp/=g,zz/=g;
exgcd(yy,b,x,y);
b=abs(b);
x=((zz*x)%b+b)%b;
if(x<0)
x+=b;
printf("%lld\n",x);
}
}
if(k==3)
{
ll yy,zz,pp;
for(int i=1;i<=t;++i)
{
mp.clear();
scanf("%lld%lld%lld",&yy,&zz,&pp);
if(gcd(yy,pp)!=1)
{
printf("Orz, I cannot find x!\n");
continue;
}
ll m=(ll)ceil(sqrt(pp)),ans,pd=0;
for(int j=0;j<=m;++j)
{
if(j==0)
{
ans=zz%pp;
mp[ans]=j;
continue;
}
ans=(ans*yy)%pp;
mp[ans]=j;
}
ll x=ksm(yy,m,pp);
ans=1;
for(int i=1;i<=m;++i)
{
ans=(ans*x)%pp;
if(mp[ans])
{
x=i*m-mp[ans];
pd=1;
printf("%lld\n",x);
break;
}
}
if(pd==0)
printf("Orz, I cannot find x!\n");
}
}
}