剑指offer.C++ 浅析BSGS算法

前言

数论大法好,人间真善美。。。


BSGS算法

一般用来求解B^{L}==N( mod P )成立的最小的L的解

对于求解这道题,要先进行分解

设 L = i * x - y ,就得到 B^{i*x-y} ==N(modP),即B^{i*x}/B^{y}=N(modP)

再移项B^{i*x}/B^{y}/N=1(modP)

 

B^{y}*N=B^{i*x}(modP)

然后就是循环一遍 y 的值,将其存入HASH表中

在循环枚举 i ,求解出第一个满足这个式子的值就是最小值 ans = i * x -  y 

 

板题

Discrete Logging


代码

数论的东西真恶心。。

结合代码理解消化。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#define ll long long
using namespace std;

ll a , b , c , cq ;
map <ll,ll> M ;

ll ksm(ll x ) //快速幂
{
	ll sum = 1 , cs = a ;
	while( x > 0 )	{
		if( x % 2 == 1 )
			sum = ( sum * cs ) % c;
		x /= 2 ;
		cs = (cs*cs) % c ;
	}
	return sum ;
}

int main()
{
	while(scanf("%lld%lld%lld", &c , &a , &b ) != EOF ) {
		M.clear() ;//HASH表初始化
		bool j = 0;
		if( a % c == 0 ) {
			printf("no solution\n");//判断是否有解
			continue;
		}
		cq = ceil(sqrt( c ) ) ;// x 的值为 sqrt(c) 不要问我why
		ll m = 0 ;
		for(int i = 0 ; i <= cq ; ++ i ) {
			if( i == 0 ) {
				m = b % c ;
				M[m] = i+1;
				continue;
			}
			m = (m*a) % c ;
			M[m] = i + 1;
		}
		ll q = ksm( cq ) ;
		m = 1 ;
		for(int i = 1 ; i <= cq ; ++ i ) {//枚举 y 的值
			m = m * q % c ;
			if( M[m] ) {
				ll ans = i*cq-M[m]+1;//求解出 ans 
				j = 1 ;
				printf("%lld\n", ( ans%c + c ) % c );
				break;
			}
		}
		if( !j )
			printf("no solution\n");
	} 
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值