题目:
题目链接:计算器
题解:
一道三个小函数的集合,一道板子题,写个博客记录一下,还是要先%%%%%%%hsm%%%%%%%帮我找到了错误,一定要记得是扩展BSGS(就是处理一下非素数的情况,就是除一下gcd即可),还是没好好看题啊,,(〃>_<;〃),
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL yy,z,p,n,k,a,b;
class hash
{
public:
hash(){memset(a,0xff,sizeof(a));}
int locate(LL x)
{
LL l=x%MOD;
while(a[l]!=x&&a[l]!=-1) l=(l+1)%MOD;
return l;
}
void insert(LL x,LL va)
{
LL l=locate(x);
if(a[l]==-1) a[l]=x,v[l]=va;
}
LL get(LL x)
{
LL l=locate(x);
return a[l]==x?v[l]:-1;
}
void clear(){memset(a,0xff,sizeof(a));}
private:
static const LL MOD=100007;
LL a[MOD+100],v[MOD+100];
}H;
LL ksm(LL a,LL b,LL mod)
{
LL s=1;
while(b)
{
if(1&b) s=(s*a)%mod;
b>>=1; a=(a*a)%mod;
}
return s;
}
LL exgcd1(LL a,LL b,LL &x ,LL &y)
{
LL t,s;
if(!b){x=1,y=0; return a;}
s=exgcd1(b,a%b,x,y);
t=x,x=y,y=t-a/b*y;
return s;
}
LL Gcd(LL a,LL b){return b?Gcd(b,a%b):a;}
void BSGS(LL yy,LL z,LL p)//扩展BSGS
{
LL d=1,y,x,m,t=1;
if(yy==0&&z==0){printf("1\n");return;}
if(yy==0&&z!=0){printf("Orz, I cannot find x!\n");return ;}
H.clear();
m=ceil(sqrt(double(p)));
LL tmp=1,cnt=0l;
LL gcd=Gcd(yy,p);
while(gcd!=1)//对于非素数的处理
{
if(z%gcd!=0) {printf("Orz, I cannot find x!\n");return ;}
z/=gcd; p=gcd; tmp*=(yy/gcd)%p;
cnt++;
}
for(int i=0;i<m;i++) H.insert(t,i),t=t*yy%p;
for(int i=0;i<m;i++)
{
exgcd1(d,p,x,y);
x=((x*z)%p+p)%p; y=H.get(x);
if(y!=-1) {printf("%lld\n",i*m+y);return;}
d=(d*t)%p;
}
printf("Orz, I cannot find x!\n");
return ;
}
int main()
{
// freopen("a.txt","r",stdin);
scanf("%lld%lld",&n,&k);
if(k==1)//快速幂即可
{
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&yy,&z,&p);
printf("%lld\n",ksm(yy,z,p));
}
}
else if(k==2)//直接exgcd即可
{
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&yy,&z,&p);
LL x,y;
LL gcd=exgcd1(yy,p,x,y);
if(z%gcd) puts("Orz, I cannot find x!");
else
{
int tm=p/gcd;
while(x<0) x+=tm;
printf("%lld\n",((x*z/gcd)%tm+tm)%tm);
}
}
}
else//扩展BSGS的板子即可(千万记得是扩展!!!)
{
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&yy,&z,&p);
BSGS(yy,z,p);
}
}
return 0;
}