BSGS 学习笔记

在这里插入图片描述
B S G S BSGS BSGS 算法可以在 O ( n ) O(\sqrt n) O(n ) 的时间内求出上述的同余式。

m = ⌈ p ⌉ m = \left\lceil\sqrt p\right\rceil m=p ,若有解,则最小非负整数解 一定在 [ 0 , p ] [0,p] [0,p] 内,所以设 x = i × m − j x = i \times m - j x=i×mj

将式子变形, a i × m − j ≡ b ( m o d    p ) ⇒ a i × m ≡ b × a j ( m o d    p ) a^{i \times m - j} \equiv b (\mod p) \Rightarrow a^{i \times m} \equiv b \times a^j(\mod p) ai×mjb(modp)ai×mb×aj(modp)

这样我们枚举 j j j,范围 [ 0 , m ] [0,m] [0,m],将 b × a j b \times a^j b×aj 存入哈希表。

然后枚举 i i i,范围 [ 1 , m ] [1,m] [1,m],从哈希表中寻找第一个满足 a i × m ≡ b × a j ( m o d    p ) a^{i \times m} \equiv b \times a^j(\mod p) ai×mb×aj(modp),此时 x = i × m − j x = i \times m - j x=i×mj 即为所求的答案。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <limits.h>
#define re register
#define int long long
#define drep(a,b,c) for(re int a(b) ; a>=(c) ; --a)
#define rep(a,b,c) 	for(re int a(b) ; a<=(c) ; ++a)
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
inline void print(int x){
	if(x < 0) putchar('-'),x = -x;
	if(x >= 10) print(x / 10);
	putchar(x % 10 + '0');
}
int p,b,n,fl,ans=LONG_LONG_MAX;
map<int,int> mp;
signed main(){
	p = read(),b = read(),n = read();
	int m = sqrt(p);
	int mul = 1;
	rep(i,0,m-1) mp[n*mul%p] = i,mul=mul*b%p;
	int base = 1;
	rep(i,0,m){
		if(mp[base]) fl = 1,ans = min(ans,(i*m-mp[base]+p)%p);
		base = base*mul%p;
	}
	if(fl) printf("%lld\n",ans);
	else printf("no solution");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值