Description
Little Y finds there is a very interesting formula in mathematics:
XY mod Z = K
Given X, Y, Z, we all know how to figure out K fast. However, given X, Z, K, could you figure out Y fast?
Input
Input data consists of no more than 20 test cases. For each test case, there would be only one line containing 3 integers X, Z, K (0 ≤ X, Z, K ≤ 109).
Input file ends with 3 zeros separated by spaces.
Input file ends with 3 zeros separated by spaces.
Output
For each test case output one line. Write "No Solution" (without quotes) if you cannot find a feasible Y (0 ≤ Y < Z). Otherwise output the minimum Y you find.
Sample Input
5 58 33
2 4 3
0 0 0
Sample Output
9
No Solution
题解
扩展BSGS:
当模数 $c$ 不是质数的时候,显然不能直接使用 $BSGS$ 了,考虑它的扩展算法。
前提:同余性质。
令 $d = gcd(a, c)$ , $A = a cdot d,B = b cdot d, C = c cdot d$
则 $a cdot d equiv b cdot d pmod{c cdot d}$
等价于 $a equiv b pmod{c}$
因此我们可以先消除因子。
对于现在的问题 $(A cdot d)^x equiv B cdot d pmod{C cdot d}$ 当我们提出 $d = gcd(a, c)$ ($d
eq 1$)后,原式化为 $A cdot (A cdot d)^{x-1} equiv B pmod{C}$ 。
即求 $D cdot A^{x-cnt} equiv B pmod{C}$ ,令 $x = i cdot r-j+cnt$ 。之后的做法就和 $BSGS$ 一样了。
值得注意的是因为这样求出来的解 $x geq cnt$ 的,但有可能存在解 $x < cnt$ ,所以一开始需要特判。
1 //It is made by Awson on 2018.1.15 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Abs(a) ((a) < 0 ? (-(a)) : (a)) 17 #define Max(a, b) ((a) > (b) ? (a) : (b)) 18 #define Min(a, b) ((a) < (b) ? (a) : (b)) 19 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 20 using namespace std; 21 const LL MOD = 233333; 22 void read(LL &x) { 23 char ch; bool flag = 0; 24 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); 25 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 26 x *= 1-2*flag; 27 } 28 void write(LL x) { 29 if (x > 9) write(x/10); 30 putchar(x%10+48); 31 } 32 33 LL a, b, c, ans; 34 struct MAP { 35 LL ha[MOD+5]; int id[MOD+5]; 36 void clear() {for (int i = 0; i < MOD; i++) ha[i] = id[i] = -1; } 37 int count(LL x) { 38 LL pos = x%MOD; 39 while (true) { 40 if (ha[pos] == -1) return 0; 41 if (ha[pos] == x) return 1; 42 ++pos; if (pos >= MOD) pos -= MOD; 43 } 44 } 45 void insert(LL x, int idex) { 46 LL pos = x%MOD; 47 while (true) { 48 if (ha[pos] == -1 || ha[pos] == x) {ha[pos] = x, id[pos] = idex; return; } 49 ++pos; if (pos >= MOD) pos -= MOD; 50 } 51 } 52 int query(LL x) { 53 LL pos = x%MOD; 54 while (true) { 55 if (ha[pos] == x) return id[pos]; 56 ++pos; if (pos >= MOD) pos -= MOD; 57 } 58 } 59 }mp; 60 61 LL quick_pow(LL a, LL b, LL c) { 62 LL ans = 1; 63 while (b) { 64 if (b&1) ans = ans*a%c; 65 a = a*a%c, b >>= 1; 66 } 67 return ans; 68 } 69 LL gcd(LL a, LL b) {return b ? gcd(b, a%b) : a; } 70 LL exBSGS(LL a, LL b, LL c) { 71 if (b == 1) return 0; 72 LL cnt = 0, d = 1, t; 73 while ((t = gcd(a, c)) != 1) { 74 if (b%t) return -1; 75 ++cnt, b /= t, c /= t, d = d*(a/t)%c; 76 if (d == b) return cnt; 77 } 78 mp.clear(); 79 LL tim = ceil(sqrt(c)), tmp = b%c; 80 for (int i = 0; i <= tim; i++) { 81 mp.insert(tmp, i); tmp = tmp*a%c; 82 } 83 t = tmp = quick_pow(a, tim, c); tmp = (tmp*d)%c; 84 for (int i = 1; i <= tim; i++) { 85 if (mp.count(tmp)) return tim*i-mp.query(tmp)+cnt; 86 tmp = tmp*t%c; 87 } 88 return -1; 89 } 90 void work() { 91 while ((~scanf("%lld%lld%lld", &a, &c, &b))) { 92 if (c == 0) return; 93 if ((ans = exBSGS(a%c, b%c, c)) == -1) printf("No Solution "); 94 else write(ans), putchar(' '); 95 } 96 } 97 int main() { 98 work(); 99 return 0; 100 }