[SDOI2011]计算器
作者:互联网
通过我的第一篇没看题解的SD省选题祭qwq
虽然我花了2个上午才调出来
1.k=1时,快速幂,不会快速幂的,右转pj***。
2.k=2时,扩欧,注意要判负。
这里扯一下判负方法:
将\(a\)判负,模数为\(p\),柿子是:
\[(a \bmod p +p) \bmod p\]
3.k=3时,BSGS,我感觉我以前一直在写假的BSGSqwq
详情见代码。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
ll T,k;
ll y,z,mod;
ll xx,yy;
char ch[30]={"Orz, I cannot find x!"};
map<ll,ll> ma;
inline void readx(ll &x)//快读
{
x=0;int s=1;char ch=getchar();
while(ch<'0'||ch>'9')
{if(ch=='-') s=-1;ch=getchar();}
while(ch>='0'&&ch<='9')
{x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
x*=s;
}
inline ll qpow(ll b,ll p)//快速幂
{
ll ans=1;
while(p)
{
if(p&1) ans=ans*b%mod;
b=b*b%mod;
p>>=1;
}
return ans;
}
inline ll gcd(ll a,ll b)//最大公约数,欧几里得算法
{
if(b==0) {return a;}
return gcd(b,a%b);
}
inline void exgcd(ll a,ll b,ll &xx,ll &yy)//扩欧算法
{
if(!b) {xx=1;yy=0;return;}
exgcd(b,a%b,yy,xx);
yy-=a/b*xx;
}
inline ll inverse(ll x)//费马小定理求逆元
{return qpow(x,mod-2);}
inline void bsgs(ll a,ll b)//BSGS算法
{
a%=mod;b%=mod;
ma.clear();
ll m=ll(sqrt(mod+1)),e=1;
for(int j=0;j<m;++j)//将所有的m-1个a^j计入哈希表里
{
if(!ma.count(e)) ma[e]=j;
e=e*a%mod;
}
if(gcd(e,mod)!=1) {puts(ch);return;}//如果a^j和模数互质,那BSGS就没法算了,所以无解
ll inv=inverse(e);
for(int i=0;i<m;++i)
{
if(ma.count(b))
{
ll ans=i*m+ma[b];
printf("%lld\n",ans);
return;
}
b=b*inv%mod;
}
puts(ch);
}
int main()
{
readx(T);readx(k);
if(k==1) while(T--)
{
readx(y);readx(z);readx(mod);
printf("%lld\n",qpow(y,z));
}
else if(k==2) while(T--)
{
readx(y);readx(z);readx(mod);
ll g=gcd(y,mod);
if(z%g) {puts(ch);continue;}
exgcd(y,mod,xx,yy);
ll ans=(xx*z/g%mod+mod)%mod;
printf("%lld\n",ans);
}
else if(k==3) while(T--)
{
readx(y);readx(z);readx(mod);
bsgs(y,z);
}
return 0;
}
//为了好调,我有些压行。不要喷我码风毒瘤啊qwq
emmm,分享一下我的学习笔记吧qwq
标签:ch,return,ll,yy,SDOI2011,xx,计算器,include 来源: https://www.cnblogs.com/oierwyh/p/11372182.html