BSGS算法

问题:给定三个数a,b,p,保证a,p互质,求解 a x ≡ b   ( m o d   p ) a^x\equiv b \ (mod \ p) axb (mod p)
最小正整数 x x x     1 < = a , b , p < = 1 0 9 \ \ \ 1<=a,b,p<=10^9    1<=a,b,p<=109

BSGS(拔山盖世 大步小步算法)
根据欧拉定理: a φ ( n ) ≡ 1 a^{\varphi (n)}\equiv 1 aφ(n)1 ( m o d (mod (mod n ) n) n)
可以看出指数的同余的循环节
直接暴力时间复杂度 O ( φ ( n ) ) O(\varphi (n)) O(φ(n))
考虑优化
x = p ′ q − r x=p'q-r x=pqr (同余常见搞法,设 a = p b + r a=pb+r a=pb+r 加减一样)
A p ′ q ≡ b ∗ A r A^{p'q}\equiv b*A^r ApqbAr ( m o d (mod (mod n ) n) n)
首先在 O ( p ′ ) O(p') O(p)内求出 a a a a p ′ − 1 a^{p'-1} ap1每一个的值( a , a 2 , a 3 . . . a,a^2,a^3... a,a2,a3...
并把这些值存入哈希表
然后枚举 q q q,每次从哈希表中查询是否有满足原式的值
时间复杂度 O ( m a x ( p ′ , φ ( p ) / p ′ ) ) O(max(p',\varphi (p)/p')) O(max(p,φ(p)/p))
显然最优是令 p ′ = φ ( p ) p'=\sqrt{\varphi (p)} p=φ(p)
总的时间复杂度 O ( φ ( p ) ) O(\sqrt{\varphi (p)}) O(φ(p) )
That’s all.

C o d e Code Code

( p p p为质数, a , p a,p a,p互质还可以求 φ ( p ) \varphi (p) φ(p))
模板题:SDOI2011 计算器
TJOI2007 可爱的质数

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int Mod=1e5+7;
const int MAXN=1<<20;
struct w{
	int to,nx,s;
	w(){s=-1;}
}Hash[MAXN+10];
int a[Mod+10],tot=0;

inline void add(int,int,int,int);
void Insert(int);
int Query(int);
void BSGS(int,int,int);

signed main(){
	//freopen ("std.in","r",stdin);
	//freopen ("std.out","w",stdout);
	int p,b,n;
	scanf("%lld%lld%lld",&p,&b,&n);
	BSGS(p,n,b);
	return 0;
}

inline void add(int x,int i,int val,int s){Hash[i].to=val,Hash[i].s=s,Hash[i].nx=a[x],a[x]=i;}
void Insert(int val,int s){
	int x=val%Mod;
	add(x,++tot,val,s);
}

int Query(int val){
	int x=a[val%Mod];
	while (Hash[x].to!=val && Hash[x].to)	x=Hash[x].nx;
	return Hash[x].s;
}

void BSGS(int p,int n,int a){
	int m=sqrt(p)+1,t=1,tt;
	for (register int i=0;i<m;++i){
	 	Insert((t*n)%p,i);
	 	t=(t*a)%p;
	}
	tt=t;
	for (register int i=1;i<=m;++i){
		int k=Query(t);
		t=(t*tt)%p;
		if (k==-1)	continue;
		printf("%lld\n",i*m-k);
		return;
	}
	printf("no solution\n");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值