蒟蒻求助exBSGS
查看原帖
蒟蒻求助exBSGS
376265
BrotherCallIllenials楼主2021/6/16 16:34

请问各位巨佬这题能不能用Lower_Bound(这里用二分实现)代替Map或哈希。如果不行,那么为什么?

用map是TLE了一个点,而二分却WA了7个点。随机数对拍没对出来问题,求Hack数据。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define int long long
using namespace std;

int a,p,b;
struct edge{
	int num , r;
}M[1000010];

int gcd(int x,int y){
	return y?gcd(y , x % y):x;
}

int ksm(int x,int y,int mod){
	int temp = 1;
	for(;y;y>>=1,x = x * x % mod)
		if(y & 1)
			temp = temp * x % mod;
	return temp;
}

bool compare(edge s1,edge s2){
	return s1.r < s2.r;
}

void exgcd(int A,int B,int &x,int &y){
	if(B == 0){x = 1;y = 0;return ;}
	exgcd(B , A % B , y , x);
	y -= A / B * x;
}

int BSGS(int x,int y,int z){
	int t = ceil(sqrt(z));
	int ks = 1;
	for(int i=1;i<=t;i++){
		ks = ks * x % z;
		int now = y * ks % z;
		M[i].num = i;
		M[i].r = now;
	}
	sort(M + 1 , M + 1 + t , compare);
	int bkp = ksm(x , t , z);
	int nxt = 1;
	for(int i=1;i<=t;i++){
		nxt = nxt * bkp % z;
		int l = 1 , r = t , as = -1;
		while(l <= r){
			int mid = l + r >> 1;
			if(M[mid].r == nxt){as = M[mid].num;break;}
			if(M[mid].r > nxt)r = mid - 1;
				else l = mid + 1;
		}
		if(as != -1)return ((i * t - as) % z + z) % z;
	}
	return -1;
}

int exBSGS(){
	int sumG = 1;
	int A = 1;
	int k = 0;
	while(true){
		int g = gcd(a , p);
		if(g == 1)break;
		if(b % g != 0)return -1;
		b /= g;
		k ++;
		sumG = sumG * g;
		p /= g;
		A = A * (a / g) % p;
		if(b == A)return k;
	}
	int inv,sy;
	exgcd(A , p , inv , sy);
	inv = (inv % p + p) % p;
	b = b * inv % p;
	int now = BSGS(a , b , p);
	if(now == -1)
		return -1;
	return now + k;
}

signed main(){
	while(true){
		cin>>a>>p>>b;
		if(a == 0 && p == 0 && b == 0)break;
		int ans = exBSGS();
		if(ans == -1){cout<<"No Solution"<<endl;continue;}
			else cout<<ans<<endl;
	}
	return 0;
}
2021/6/16 16:34
加载中...