版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/82916960
BZOJ传送门
POJ传送门
题目描述
小Y发现,数学中有一个很有趣的式子: 给出 、 、 ,我们都知道如何很快的计算 。但是如果给出 、 、 ,你是否知道如何快速的计算 呢?
输入输出格式
输入格式
本题由多组数据(不超过20组),每组测试数据包含一行三个整数 、 、 ( )。 输入文件一行由三个空格隔开的 结尾。
输出格式
对于每组数据:如果无解则输出一行No Solution
,否则输出一行一个整数
,使得其满足
,如果有多个解输出最小的一个
。
输入输出样例
输入样例#1:
5 58 33
2 4 3
0 0 0
输出样例#1:
9
No Solution
解题分析
一道扩展 的板题。
一般的 只能解决 且 为质数的情况, 如果 不互质就凉凉了。
设 , 那么我们可以将这个式子拆开成 , 如此反复操作最后可以得到 。 这时候就可以用普通的 搞操作了。
不过显然我们现在的 , 所以我们暴力枚举 的情况就好。
代码如下:
#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);
}
}