【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,,

现在才会hash是不是太弱了,,,

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
	static const int mo=100007;
	int a[100010],v[100010];
	node() {memset(a,-1,sizeof(a));}
	int find(int val){
		int pos=(val%mo+mo)%mo;
		while ((a[pos]!=val)&&(a[pos]!=-1)) pos=(pos+1)%mo;
		return pos;
	}
	void insert(int val,int x){
		int pos=find(val);
		if ((a[pos]==-1)||(a[pos]==val)){
			a[pos]=val;
			v[pos]=x;
		}
	}
	int get(int val){
		int pos=find(val);
		return a[pos]==val?v[pos]:-1;
	}
	void clear() {memset(a,-1,sizeof(a));}
}hash;
int T,L;
inline int work1(int a,int b,int n){
	long long t=a,ans=1;
	while (b){
		if (b%2==1) ans=(ans*t)%n;
		b=b/2;
		t=(t*t)%n;
	}
	return (int)ans;
}
inline int exgcd(int a,int b,int &x,int &y){
	if (b==0){
		x=1; y=0; return a;
	}else{
		int r=exgcd(b,a%b,x,y);
		int t=y;
		y=x-a/b*y;
		x=t;
		return r;
	}
}
inline void work2(int a,int b,int n){
	int x,y;
	int d=exgcd(a,n,x,y);
	if (b%d) puts("Orz, I cannot find x!\n");
	else printf("%d\n",(int)((((long long)x*b/d%n)+n)%n));
}
inline void work3(int a,int b,int n){
	if ((a%n==0)&&(b!=0)) {puts("Orz, I cannot find x!\n"); return;}
	hash.clear();
	int m=ceil(sqrt(n));
	long long t=b%n;
	for(int i=0;i<=m;++i){
		hash.insert((int)t,i);
		t=(t*a)%n;
	}
	int s=work1(a,m,n); t=s;
	for(int i=1;i<=m;++i){
		int v=hash.get((int)t);
		if (v!=-1) {printf("%d\n",i*m-v); return;}
		t=(t*s)%n;
	}
	puts("Orz, I cannot find x!\n");
}
int main(){
	scanf("%d %d\n",&T,&L);
	int y,z,p,a,b;
	switch (L){
		case 1:
			while (T--){
				scanf("%d %d %d\n",&y,&z,&p);
				printf("%d\n",work1(y,z,p));
			}
		break;
		case 2:
			while (T--){
				scanf("%d %d %d\n",&y,&z,&p);
				work2(y,z,p);
			}
		break;
		case 3:
			while (T--){
				scanf("%d %d %d\n",&y,&z,&p);
				work3(y,z,p);
			}
		break;
	}
	return 0;
}

这样就可以啦

你可能感兴趣的:(【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法)