[SDOI2011]计算器 BSGS
前两个操作都看出来做法了,第三个要用到BSGS这个算法
BSGS主要可以解 a^x=b(mod n)的 0<=x<n 的解
暂时先拿kb和hzwer的板子当黑盒吧。。数论细节短时间内没有学的打算
upd:
学了一下BSGS算法的的理论以及这个板子的实现,似乎这个板子默认模数素数
模数不素的话用kb的吧,那个似乎是用前向星处理哈希冲突做的。。
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const ll Linf=9e18; const int maxn=1e5+7; const ll mod=100003; const double eps=1e-6; int gcd(int a,int b){return b==0?a:gcd(b,a%b);} void exgcd(int a,int b,int &x,int &y){ if(b==0){x=1;y=0;return;} exgcd(b,a%b,x,y); int t=x;x=y;y=t-a/b*y; } int work1(ll y,int z,int p){ y%=p; ll ans=1; for(int i=z;i;i>>=1,y=y*y%p) if(i&1)ans=ans*y%p; //printf("%d\n",ans); return ans; } void work2(int y,int z,int p){ //xy+tp=z,求x最小正数解 int g=gcd(y,p); if(z%g){puts("Orz, I cannot find x!");return;} y/=g;z/=g;p/=g; int a,b;exgcd(y,p,a,b); a=(ll)a*z%p; while(a<0)a+=p; printf("%d\n",a); } map<int,int>mp; void work3(int y,int z,int p){ y%=p; if(!y&&!z){puts("1");return;} if(!y){puts("Orz, I cannot find x!");return;} mp.clear(); ll m=ceil(sqrt(p)),t=1; mp[1]=m+1; for(ll i=1;i<m;i++){ t=t*y%p; if(!mp[t])mp[t]=i; } ll tmp=work1(y,p-m-1,p),ine=1; for(ll k=0;k<m;k++){ int i=mp[z*ine%p]; if(i){ if(i==m+1)i=0; printf("%lld\n",k*m+i); return; } ine=ine*tmp%p; } puts("Orz, I cannot find x!"); } int main(){ int T,K;scanf("%d%d",&T,&K); for(int i=1;i<=T;i++){ int y,z,p;scanf("%d%d%d",&y,&z,&p); if(K==1){ int ans=work1(y,z,p); printf("%d\n",ans); }else if(K==2){ work2(y,z,p); }else{ work3(y,z,p); } } }