1. 程式人生 > 實用技巧 >P3846 [TJOI2007] 可愛的質數/【模板】BSGS

P3846 [TJOI2007] 可愛的質數/【模板】BSGS

稍後更新

題面

題意:

給定\(p,b,n\),求滿足\(b^{x}\equiv n\ (mod\ p)\)的最小的\(x\)的值

演算法分析:

根據題意我們很容易想到這個題用\(BSGS\)(大步小步演算法或北上廣深或拔山蓋世)來做,\(BSGS\)就是用來處理這一類問題的

\(BSGS\)中的\(p\)為質數

實現:

我們考慮柿子\(b^{x}\equiv n\ (mod\ p)\)

根據費馬小定理\(a^{p-1}\equiv 1\ (mod\ p)\)(證明在我的另一篇部落格裡有提到過),且\(a^{0}\equiv 1\ (mod\ p)\)

我們可以發現\(a^{x}\equiv n\ (mod\ p)\)

中,當\(x \in [0,p-1)\)時,\(a^{x} mod \ p\) 構成了\(mod\ p\)的一個完全剩餘系

我們就可以發現\([0, p-2]\)是一個迴圈節,且每個迴圈節都會構成一個\(mod\ p\) 的完全剩餘系

所以我們只需要考慮\(x\in [0,p-2]\)中,\(a^{x}\equiv n\ (mod\ p )\)

然後我們設$m= $

#include<bits/stdc++.h>
using namespace std;
long long n, b, p, m, ans, now, st;
map<long long, int> mp;
long long ksm(long long x, long long y){
	long long res = 1;
	while(y){
		if(y & 1) res = (res * x) % p;
		x = (x * x) % p;
		y >>= 1;
	}
	return res % p;
}
int main(){
	mp.clear();
	scanf("%d %d %d", &p, &b, &n);
	if(b % p == 0){
		printf("no solution\n");
		return 0;
	}
	m = ceil(sqrt(p));
	now = n % p;
	mp[now] = 0;
	for(int i = 1; i <= m; i ++){
		now = (now * b) % p;
		mp[now] = i;
	}
	st = ksm(b, m);
	now = 1;
	for(int i = 1; i <= m; i ++){
		now = (now * st) % p;
		if(mp[now]){
			ans = i * m - mp[now];
			printf("%lld\n", ((ans % p) + p) % p);
			return 0;
		}
	}
	printf("no solution\n");
	return 0;
}