poj2417: bsgs算法模板

bsgs算法用来解决有关A^x ≡ B (mod C)的方程, 求x

把x看成 i*m-j,上面的式子就可以变成A^(i * m - j) ≡ B (mod C)    =>    A^(i * m) ≡ B * A^j (mod C)

具体解释看这个:https://blog.csdn.net/clover_hxy/article/details/50683832

这个博客是用map写的,我用map写完交这个题的时候刚好卡过去,大概是用4700ms左右

之后又把map改成哈希只用了16ms!!!!

map和哈希的时间差300倍!!!!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;

struct Thash{//相当于map 
    static const int MOD=233333;
    static const int MAXN=1e6+5;
    int tot,head[MOD+100],next[MAXN],h[MAXN],val[MAXN];
    inline void clear(){tot=0;memset(head,0,sizeof head);}
    inline void insert(int H,int VAL){//map<H, VAL>; 
        for(int i=head[H%MOD];i;i=next[i]) if(h[i]==H){val[i]=VAL;return ;}
        h[++tot]=H;val[tot]=VAL;next[tot]=head[H%MOD];head[H%MOD]=tot;
    }
    inline int get(int H){//map[H];
        for(int i=head[H%MOD];i;i=next[i]) if(h[i]==H) return val[i];
        return 0;
    }
}M;
ll qpow(ll a, ll b, ll mod) {ll ans = 1;while (b) {if (b % 2) ans = ans * a % mod;a = a * a % mod;b /= 2;}return ans;}
ll bsgs(ll A, ll B, ll C) {//A^x = B (mod C)  =>  A^(i * m - j) = B (mod C)  =>  A^(i * m) = B * A^j (mod C)
	if (A % C == 0)
		return -1;
	if(B % C == 0)
		return 1;
	M.clear();
	ll m = ceil(sqrt((double)C));
	ll temp = B % C;
	for (int i = 0; i <= m; i++) {//先暴力 B * A^j 把 j 存到mp里 
		M.insert(temp, i);
		temp = temp * A % C;
	}
	ll t = qpow(A, m, C);
	temp = 1;
	for (int i = 1; i <= m; i++) {
		temp = temp * t % C;
		int u = M.get(temp);
		if (u) {
			ll ans = (i * m % C - u % C + C) % C;
			return ans;
		}
	}
	return -1;
}//-1代表无解

int main() {
	ll A ,B, C;
	while (scanf("%lld%lld%lld", &C, &A, &B) != EOF) {
		ll ans = bsgs(A, B, C);
		if (ans != -1)
			printf("%lld\n", ans);
		else
			printf("no solution\n");
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值