【bzoj2242】[SDOI2011]计算器 快速幂+BSGS

来源:互联网 发布:黑帽seo 编辑:程序博客网 时间:2024/05/30 23:41
第一问,快速幂
第二问,exgcd或
p是质数,所以y一定有逆元
x=y^(-1)*z
其中y^(-1)=y^(P-2)
因为0没有逆元,所以只有y=0时无解
第三问,BSGS
设x=bk+c
其中k=sqrt(P),b和c都小于sqrt(P)
Y^(bk+c)=Z
Y^(bk)=Z*Y^(-c)
用map记录一下Z*Y^(-c),一共sqrt(P)个数
枚举b,查询有没有对应的Z*Y^(-c),如果有,则更新答案
0要特判

复杂度O(sqrt(P)*logP)


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<iostream> #include<map>using namespace std;int mod,y,z,k,T,n;map<int,int> mp;int power(int x,int y,int mod){int ans=1;while (y){if (y&1) ans=(long long)ans*x%mod;x=(long long)x*x%mod;y>>=1;}return ans;}void BSGS(int y,int z,int mod){if (y==0 && z==0) {printf("1\n");return;}if (y==0 && z!=0) {printf("Orz, I cannot find x!\n");return;}mp.clear();int temp=1,p=power(y,mod-2,mod),k=ceil(sqrt(mod));mp[z]=k+1;for (int i=1;i<k;i++){temp=(long long)temp*p%mod;int t=(long long)temp*z%mod;if (!mp[t]) mp[t]=i;}temp=1;p=power(y,k,mod);for (int i=0;i<k;i++,temp=(long long)temp*p%mod){if (mp[temp]){if (mp[temp]==k+1) printf("%d\n",i*k);else printf("%d\n",i*k+mp[temp]);return;}}printf("Orz, I cannot find x!\n");}int main(){scanf("%d%d",&n,&T);for (int i=1;i<=n;i++){scanf("%d%d%d",&y,&z,&mod);y%=mod;if (T==1) printf("%d\n",power(y,z,mod));elseif (T==2){z%=mod;if (y==0 && z!=0) printf("Orz, I cannot find x!\n");else printf("%d\n",(long long)z*power(y,mod-2,mod)%mod);}else z%=mod,BSGS(y,z,mod);}return 0;}


0 0
原创粉丝点击