【bzoj2242】 SDOI2011—计算器
http://www.lydsy.com/JudgeOnline/problem.php?id=2242 (题目链接)
题意
给出y,z,p。求:1.yz mod p;2.xy=z(mod p);3.yx=z(mod p)。
Solution
1.快速幂
2.exgcd
3.BSGS
细节
数学题就是细节多,具体看代码。
代码
// bzoj2242 #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<map> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; map<int,int> mp; LL power(LL a,LL b,LL c) { LL res=1; while (b) { if (b&1) res=res*a%c; b>>=1;a=a*a%c; } return res; } void exgcd(LL a,LL b,LL &d,LL &x,LL &y) { if (b==0) {d=a;x=1;y=0;return;} exgcd(b,a%b,d,y,x); y-=a/b*x; } LL BSGS(LL a,LL b,LL p) { //求解a^x=b(mod p),p为素数,无解返回-1. if (a%p==0 && b==0) return 1; if (a%p==0) return -1; mp.clear();mp[1]=0; //注意a^0=1 int m=ceil(sqrt(p)); //向上取整,避免漏解 LL inv=power(a,p-m-1,p),e=1; //inv为a^m的逆元,用费马小定理求 for (int i=1;i<m;i++) { //求e[i]数组 e=e*a%p; if (!mp.count(e)) mp[e]=i; } for (int i=0;i<m;i++) { //枚举a^(im),a^(im+1),a^(im+2)~~~ if (mp.count(b)) return mp[b]+i*m; //一定要是mp.count(),因为mp[b]可能为0 else b=b*inv%p; } return -1; } int main() { LL T,K,Y,Z,P;scanf("%lld%lld",&T,&K); while (T--) { scanf("%lld%lld%lld",&Y,&Z,&P); if (K==1) printf("%lld\n",power(Y,Z,P)); if (K==2) { LL x,y,d; exgcd(Y,P,d,x,y); if (Z%d!=0) puts("Orz, I cannot find x!"); else printf("%lld\n",((Z/d)*x%(P/d)+(P/d))%(P/d)); } if (K==3) { LL ans=BSGS(Y,Z,P); if (ans==-1) puts("Orz, I cannot find x!"); else printf("%lld\n",ans); } } return 0; }
This passage is made by MashiroSky.