[BZOJ 1467] [POJ 3243] clever Y

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/82916960

BZOJ传送门

POJ传送门

题目描述

小Y发现,数学中有一个很有趣的式子: X Y   m o d   Z = K X^Y\ mod\ Z = K 给出 X X Y Y Z Z ,我们都知道如何很快的计算 K K 。但是如果给出 X X Z Z K K ,你是否知道如何快速的计算 Y Y 呢?

输入输出格式

输入格式

本题由多组数据(不超过20组),每组测试数据包含一行三个整数 X X Z Z K K 0 X , Z , K 1 0 9 0 \le X, Z, K \le 10^9 )。 输入文件一行由三个空格隔开的 0 0 结尾。

输出格式

对于每组数据:如果无解则输出一行No Solution,否则输出一行一个整数 Y ( 0 Y < Z ) Y(0 \le Y < Z) ,使得其满足 X Y   m o d   Z = K X^Y\ mod\ Z = K ,如果有多个解输出最小的一个 Y Y

输入输出样例

输入样例#1:

5 58 33
2 4 3
0 0 0

输出样例#1:

9
No Solution

解题分析

一道扩展 B S G S BSGS 的板题。

一般的 B S G S BSGS 只能解决 A X B ( m o d   C ) A^X\equiv B(mod\ C) C C 为质数的情况, 如果 A C A、C 不互质就凉凉了。

d = g c d ( A , C ) d=gcd(A,C) , 那么我们可以将这个式子拆开成 A d A x 1 B d ( m o d   C d ) \frac{A}{d}A^{x-1}\equiv \frac{B}{d}(mod\ \frac{C}{d}) , 如此反复操作最后可以得到 P × A x n u m B ( m o d   C ) P\times A^{x-num}\equiv B'(mod\ C') 。 这时候就可以用普通的 B S G S BSGS 搞操作了。

不过显然我们现在的 x > n u m x>num , 所以我们暴力枚举 x n u m x\le num 的情况就好。

代码如下:

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cctype>
#include <map>
#define W while
#define IN inline
#define gc getchar()
#define R register
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
std::map <int, int> mp;
int exgcd(R int a, R int b, int &x, int &y)
{
	if(!b) return x = 1, y = 0, a;
	int ret = exgcd(b, a % b, x, y);
	int buf = x; x = y, y = buf - a / b * y;
	return ret;
}
IN int EXBSGS(R int A, R int B, R int MOD)
{
	if(MOD == 1) if(!B) return 0; else return -1;
	if(B == 1) if(A) return 0; else return -1;
	if(!(A % MOD)) if(!B) return 1; else return -1;
	int num = 0, now = 1, seg = 1, gcd, x, y, bd = std::ceil(std::sqrt(MOD));
	mp.clear();
	W ((gcd = exgcd(A, MOD, x, y)) > 1)
	{
		if(B % gcd) return -1;
		B /= gcd, MOD /= gcd; ++num;
		now = 1ll * now * A / gcd % MOD;
	}
	for (R int i = 0, val = 1; i <= num; ++i, val = 1ll * val * A % MOD)
	if(val == B) return i;
	for (R int i = 0; i < bd; ++i, seg = 1ll * seg * A % MOD) if(!mp.count(seg)) mp[seg] = i;
	for (R int i = 0; i < bd; ++i, now = 1ll * now * seg % MOD)
	{
		gcd = exgcd(now, MOD, x, y);
		x = (1ll * x * B % MOD + MOD) % MOD;
		if(mp.count(x)) return i * bd + mp[x] + num;
	}
	return -1;
}
int main(void)
{
	R int A, B, MOD, ans;
	W (~scanf("%d%d%d", &A, &MOD, &B))
	{
		if(!(A | B | MOD)) break;
		ans = EXBSGS(A, B, MOD);
		if(ans < 0) puts("No Solution");
		else printf("%d\n", ans);
	}
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/82916960