bzoj 1467 exBSGS

X^Y mod Z = K 给出X、Y、Z,我们都知道如何很快的计算K。但是如果给出X、Z、K,你是否知道如何快速的计算Y呢?

 

x,z不互质:exBSGS

详见:https://blog.csdn.net/ww140142/article/details/47837521

x,z互质,用exgcd求逆元

关于逆元的几种求法和运用:

https://blog.csdn.net/acdreamers/article/details/8220787(例题)

https://blog.csdn.net/guhaiteng/article/details/52123385


数学题一定要先推清楚式子再写


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;

typedef long long ll;
ll x,y,z,k,inv;
map <int,int> mp;

ll log_(ll x){
	return (ll)(log(x) / log(2));
}
ll gcd(ll x,ll y){
	if ( !y ) return x;
	return gcd(y,x % y);
}
ll power(ll x,int y){
	ll res = 1;
	while ( y ){
		if ( y & 1 ) res = res * x % z;
		x = x * x % z;
		y >>= 1;
	}
	return res;
}
void exgcd(ll x,ll z,ll &a,ll & b){
	if ( !z ){
		a = 1 , b = 0;
		return;
	}
	exgcd(z,x % z,a,b);
	ll t = a;
	a = b , b = t - x / z * b;
}
ll getinv(ll x,ll z){
	ll a,b;
	exgcd(x,z,a,b);
	return (a % z + z) % z;
}
int BSGS(ll a,ll b){
	int sz = (int)sqrt(z) + 1; ll x = b;
	for (int i = 0 ; i <= sz ; i++){
		if ( !mp[x] ) mp[x] = i + 1;
		x = x * inv % z;
	}
	if ( mp[1] ) return mp[1] - 1;
	a = power(a,sz) , x = 1;
	for (int i = 1 ; i <= z / sz + 1 ; i++){
		x = x * a % z;
		if ( mp[x] ) return mp[x] + sz * i - 1;
	}
	return -1;
}
int check(){
	ll cur = x % z;
	for (int i = 1 ; i <= log_(z) + 1 ; i++){
		if ( cur == k ) return i - 1;
		cur = cur * x % z;
	}
	int cnt = 0; ll d = gcd(x,z),p = d;
	while ( d != 1 ){
		cnt++ , z /= d;
		d = gcd(x,z) , p = p * d;
	}
	if ( k % p != 0 ) return -1;
	inv = getinv(x,z);
	k = k * power(inv,cnt) % z;
	int ans = BSGS(x,k);
	if ( ans == -1 ) return -1;
	return ans + cnt;
}
int main(){
	freopen("input.txt","r",stdin);
	while ( 1 ){
		cin>>x>>z>>k;
		if ( !x && !z && !k ) break;
		mp.clear();
		int d = check();
		if ( d != -1 ) printf("%d\n",d);
		else printf("No Solution\n");
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_42484877/article/details/80882128
今日推荐