[SDOI2011]计算器 BSGS

来源:互联网 发布:iphone4移动数据开关 编辑:程序博客网 时间:2024/06/05 18:26

前两个操作都看出来做法了,第三个要用到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);}}}


原创粉丝点击