bzoj1467 Pku3243 clever Y
1467: Pku3243 clever Y
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 313 Solved: 181
[Submit][Status][Discuss]
Description
小Y发现,数学中有一个很有趣的式子: X^Y mod Z = K 给出X、Y、Z,我们都知道如何很快的计算K。但是如果给出X、Z、K,你是否知道如何快速的计算Y呢?
Input
本题由多组数据(不超过20组),每组测试数据包含一行三个整数X、Z、K(0 <= X, Z, K <= 10^9)。 输入文件一行由三个空格隔开的0结尾。
Output
对于每组数据:如果无解则输出一行No Solution,否则输出一行一个整数Y(0 <= Y < Z),使得其满足XY mod Z = K,如果有多个解输出最小的一个Y。
Sample Input
5 58 33
2 4 3
0 0 0
2 4 3
0 0 0
Sample Output
9
No Solution
No Solution
HINT
Source
分析:扩展BSGS.对于P与A不互质的情况,我们就不断地提gcd出来,直到互质.然后换元套用普通的bsgs算法即可.具体的解法:--来自Clove_unique的博客.事实上只需要根据式子就可以用普通的BSGS算法了,求出x-k后,加上k就是x.
一个思想:从普通算法向扩展算法的延伸,如果由互质版本变成不互质版本,想办法变成互质版本,可以取gcd.一定要是等价变形.在变形的时候要判断无解的情况.
#include <cstdio> #include <cmath> #include <map> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; ll a, b, p, block; map <ll, ll> m; ll gcd(ll a, ll b) { if (!b) return a; return gcd(b, a % b); } ll qpow(ll a, ll b) { ll res = 1; while (b) { if (b & 1) res = (res * a) % p; a = (a * a) % p; b >>= 1; } return res; } ll exbsgs(ll a, ll b, ll p) { if (b == 1) return 0; ll temp = gcd(a, p), cnt = 0, t = 1; while (temp != 1) { if (b % temp != 0) return -1; cnt++; b /= temp; p /= temp; t = t * (a / temp) % p; temp = gcd(a, p); } m.clear(); block = sqrt(p); ll res = b, ta = qpow(a, block); for (ll i = 1; i <= block; i++) { res = res * a % p; m[res] = i; } for (ll i = 1; i <= block; i++) { t = t * ta % p; if (m[t]) return i * block - m[t] + cnt; } return -1; } int main() { while (scanf("%lld%lld%lld", &a, &p, &b) && a && b && p) { ll ans = exbsgs(a % p, b % p, p); if (ans != -1) printf("%lld\n", ans); else puts("No Solution"); } return 0; }