POJ3243 EXT-BSGS算法

需要解决问题之前,首先要做到POJ2417,我的解决问题的方法:http://blog.csdn.net/wyfcyx_forever/article/details/40538515

如今来看这个问题:Ax≡B(mod C)

已知A,B,C<=10^9,给定A,B,C,求x的最小整数解。

注意这里的A,B,C没有不论什么限制!

那么考虑我们的传统的GSBS算法为何不能解决问题:如果枚举的某个i,我们要利用拓展欧几里得求出存不存在某个A^j(0<=j<m),使得A^(i*m)*A*j%C=B.

那么令A^j=x,我们其实要求的是一个二元方程的整数解:A^(i*m)x+Cy=B.我们知道有解当且仅当gcd(A,C)|B,然而眼下没有不论什么限制,显然是不一定满足的。

我们要对算法进行一些改动。使得其能够进行上述的处理。详细证明去看AekdyCoin犇的题解,我就是简单讲一下我的理解。

一開始的方程等价于A^x*a+C*b=B(a,b是整数)。如今gcd(A,C)!=1,最好还是令t=gcd(A,C)

我们考虑方程(A/t)A^x‘%(C/t)=(B/t)的解x‘与原来的解x有什么关系。

显然如今的方程等价于(A/t)A^x‘*a‘+(C/t)*b‘=B/t.

两端均乘以t得到:A^(x‘+1)*a‘+C*b‘=B

由系数相等有:x=x‘+1,a=a‘,b=b‘.

那么我们就有一种方法算出x了。先算出x‘,再加上1即可了。

考虑怎样求出x‘,如今的方程假设A,C依然不互质,就继续迭代将系数除以最大公约数。同一时候前面的常数增大。

然后求出解之后再加上总共除的次数就好了。

Code:

#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <climits>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
inline LL gcd(LL a, LL b) {
	return (!b) ? a : gcd(b, a % b);
}
inline void Exgcd(LL a, LL b, LL &d, LL &x, LL &y) {
	if (!b) { d = a, x = 1, y = 0; }
	else { Exgcd(b, a % b, d, y, x), y -= x * (a / b); }
}
inline LL Solve(LL a, LL b, LL c) {// ax%c=b S.T. (a,c)=1
	LL d, x, y;
	Exgcd(a, c, d, x, y);
	x = (x + c) % c;
	return x * b % c;
}
inline LL Ksm(LL x, LL y, LL p) {
	LL res = 1, t = x;
	for(; y; y >>= 1) {
		if (y & 1) res = res * t % p;
		t = t * t % p;
	}
	return res;
}

#define mod 1313131
struct Hashset {
	int head[mod], next[35010], f[35010], v[35010], ind;
	void reset() {
		ind = 0;
		memset(head, -1, sizeof head);
	}
	void Insert(int x, int _v) {
		int ins = x % mod;
		for(int j = head[ins]; j != -1; j = next[j])
			if (f[j] == x) {
				v[j] = min(v[j], _v);
				return;
			}
		f[ind] = x, v[ind] = _v;
		next[ind] = head[ins], head[ins] = ind++;
	}
	int operator [] (const int &x) const {
		int ins = x % mod;
		for(int j = head[ins]; j != -1; j = next[j])
			if (f[j] == x)
				return v[j];
		return -1;
	}
}S;

LL BSGS(LL C, LL A, LL B, LL p) {// A^x%p=B S.T.(A,p)=1
	if (p <= 100) {
		LL d = 1;
		for(int i = 0; i < p; ++i) {
			if (d == B)
				return i;
			d = d * A % p;
		}
		return -1;
	}
	else {
		int m = (int)sqrt(p);
		S.reset();
		LL d = 1, Search;
		for(int i = 0; i < m; ++i) {
			S.Insert(d, i);
			d = d * A % p;
		}
		for(int i = 0; i * m < p; ++i) {
			d = Ksm(A, i * m, p) * C % p;
			Search = S[Solve(d, B, p)];
			if (Search != -1)
				return i * m + Search;
		}
		return -1;
	}
}

int main() {
	LL x, z, k;
	register LL i, j;
	while(scanf("%I64d%I64d%I64d", &x, &z, &k) == 3 && (x + z + k)) {
		LL d = 1;
		bool find = 0;
		for(i = 0; i < 100; ++i) {
			if (d == k) {
				printf("%I64d\n", i);
				find = 1;
				break;
			}
			d = d * x % z;
		}
		if (find)
			continue;

		LL t, C = 1, num = 0;
		bool failed = 0;
		while((t = gcd(x, z)) != 1) {
			if (k % t != 0) {
				failed = 1;
				break;
			}
			z /= t;
			k /= t;
			C = C * x / t % z;
			++num;
		}

		if (failed) {
			puts("No Solution");
			continue;
		}

		LL res = BSGS(C, x, k, z);
		if (res == -1)
			puts("No Solution");
		else
			printf("%I64d\n", res + num);
	}

	return 0;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-10-09 19:02:55

POJ3243 EXT-BSGS算法的相关文章

bzoj2242: [SDOI2011]计算器 &amp;&amp; BSGS 算法

BSGS算法 给定y.z.p,计算满足yx mod p=z的最小非负整数x.p为质数(没法写数学公式,以下内容用心去感受吧) 设 x = i*m + j. 则 y^(j)≡z?y^(-i*m)) (mod p) 则 y^(j)≡z?ine(y^(i*m)) (mod p)(逆元) 由费马小定理y^(p-1)≡1 (mod p) 得 ine(y^m) = y^(p-m-1)  ine(y^(i*m)≡ine(y^((i?1)m))?y^(p-m-1)  1.首先枚举同余符号左面,用一个hash保存

BSGS算法学习小记(大步小步算法)

简介 先看一个式子xy≡z(modp),z是质数 现在只知道x和z,要求y. 大步小步算法(BSGS,Baby Steps Giant Steps)就是解决这个问题. 算法流程 暴搜的枚举范围 根据费马小定理:xz?1≡1. 如果y已经枚举到了z-1了,继续枚举的话就会产生循环. 所以,在暴搜中y的枚举范围就是0--z-1. 如何优化暴搜 我们想一想可不可以用分块来解决枚举的y. 把y分成p?1????√分别枚举行不行? 设m=p?1????√,y=a?m+b,这样枚举a和b就相当于分块枚举了.

BSGS算法+逆元 POJ 2417 Discrete Logging

POJ 2417 Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4860   Accepted: 2211 Description Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarith

BSGS算法_Baby steps giant steps算法(无扩展)最强详解,你从未见过的详细

Baby Steps-Varsity Giant Step-Astronauts(May'n?椎名慶治) 阅读时可以听听这两首歌,加深对这个算法的理解.(Baby steps少女时代翻唱过,这个原唱反而不是很有名……Giant Step就比较碉,是一个假面骑士片的插曲,由超碉的May'n和一个人建立的临时组合唱的,怕不怕) 这个主要是用来解决这个题: A^x=B(mod C)(C是质数),都是整数,已知A.B.C求x. 我在网上看了好多介绍,觉得他们写得都不够碉,我看不懂…于是我也来写一发. 先

BSGS算法及拓展

https://www.zybuluo.com/ysner/note/1299836 定义 一种用来求解高次同余方程的算法. 一般问题形式:求使得\(y^x\equiv z(mod\ p)\)的最小非负\(x\). \(BSGS\)算法 要求\(p\)是质数. 由费马小定理可知,\(y^{p-1}\equiv1(mod\ p)\),所以暴力枚举只要枚举到\(p?1\)即可. 但是由于\(p\)一般都很大,所以一般都跑不动... 优化算法\(ing...\) 现在令\(x=mi?j\)(其中\(m

BSGS算法初探

前言 $BSGS$算法,全称$Baby Step Giant Step$,即大小步算法.某些奆佬也称其为拔(Ba)山(Shan)盖(Gai)世(Shi)算法. 它的主要作用是求解形式如$x^t\equiv y(mod MOD)$的式子中$t$的值. 而且,它是一个简单易懂的算法(毕竟连我这样的数学渣渣都能理解). 一个简单的性质 首先,我们需要知道一个简单的性质. 由费马小定理可得,$x^{MOD-1}\equiv1(mod MOD)$. $Link$ 费马小定理详见博客筛素数方法(二)-- 费

BSGS算法!

求解关于x的方程 a^x=z(mod p),其中gcd(a,p)=1. 做法的话并不难,但是要搞懂细节还蛮多的. bsgs算法是这样的:x可以写成i*m-j的形式(这里m取值随意,但是取√p上取整时跑的最快) a^(im-j)≡z(mod p) 推得  a^im≡z*(a^j) 那么我们枚举j的值从0--(m-1),将算出的z*(a^j)加入map里面 再枚举i从1-m,将每次算出的a^im的结果去map中匹配 若匹配到,x=i*m-j. 细节 1.i的范围从1到m 证明: a ^ x Ξ b

BSGS算法(大小步算法)

$BSGS$ 算法 $Baby\ Steps\ Giant\ Steps$. 致力于解决给定两个互质的数 $a,\ p$ 求一个最小的非负整数 $x$ 使得 $a^x\equiv b(mod\ p)$ 其中 $b$ 为任意正整数,$2≤a<p$,$2≤b<p$ 该算法使用的原理与欧拉定理有关,其中$a,\ p$互质 $a^{\phi (p)}\equiv 1(mod\ p)$ 又因为 $a^0\equiv 1(mod\ p)$ 所以$0到\phi p$是一个循环节,也就是说该算法最多查找$\p

高次不定方程BSGS算法

学习数学真是一件赛艇的事. BSGS名字听起来非常有意思,力拔山兮气盖世,北上广深,小步大步...算法其实更有意思,它是用来求解一个方程的 \(A^x≡B mod P\) 是不是特别眼熟,有几个式子长的特别像,先观察一下: 一:快速幂: 求\(A^B mod P\)的值 二:乘法逆元 \(A*x ≡ 1 (mod P)\) 或者 \(A*x ≡ B (mod P)\) 三:欧拉定理 \(A^{φ(P)}≡ 1 (mod P)\) (A,P互质) 四:费马小定理 \(A^{P-1} ≡ 1 (mo

BSGS算法

问题: 给出a,b,p,求x使得a^x对p取模是b. 1.令r是一个小于根号p范围的数. 2.循环a^0,a^1,a^2......a^r-1,如果有满足条件的,算法结束. 3.否则我们设x=cr-d(为什么是-d呢,主要是为了方便后面把a^d放到右边),然后我们得到了:a^cr对p取模是b*a^d 4.现在我们观察这个式子,其中b*a^d是不变的(0<=d<r),所以我们把所有的b*a^d存入Hash,枚举c小于根号p,再看(a^r)^c是否在Hash中出现 复杂度O(p^(1/2))