Before doing this problem need to do first POJ2417, my question: http://blog.csdn.net/wyfcyx_forever/article/details/40538515
Now look at this question: A x ≡B(mod C )
Known a,b,c<=10^9, given a,b,c, the smallest integer solution of x is obtained.
Note that there is no limit to the a,b,c here!
Then consider why our traditional GSBs algorithm does not solve this problem: assuming that an enumeration of an I, we have to use the expansion of Euclid to find out that there is no one a^j (0<=j<m), so that a^ (i*m) *a*j%c=b.
So a^j=x, what we're actually asking for is an integer solution of a two-tuple equation: a^ (i*m) x+cy=b. We know that there are solutions and only if GCD (a,c) | B, however, there are no restrictions at this time, obviously not necessarily satisfied.
We have to make some modifications to the algorithm so that it can do the above processing. Specific proof to see the Aekdycoin Ben, I am just a brief explanation of my understanding.
The first equation is equivalent to A^x*a+c*b=b (A, B is an integer), now gcd (a,c)!=1, may be T=GCD (a,c)
We consider the equation (A/T) a^x '% (c/t) = (b/t) of the solution X ' in relation to the original solution x.
Obviously now the equation is equivalent to (A/T) a^x ' *a ' + (c/t) *b ' =b/t.
Both ends are multiplied by T to get: a^ (x ' + 1) *a ' +c*b ' =b
are equal by coefficients: x=x ' +1,a=a ', b=b '.
Then we have a way to figure out X. Calculate the X ', plus 1 on the line.
Consider how to find the X ', now the equation if a, C is still not coprime, continue to iterate to divide the coefficients by greatest common divisor, while the preceding constants increase.
Then we can find out the solution and add the total number of times.
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) =1ll 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 1313131struct 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) retu RN v[j];return-1;}} S ll Bsgs (ll C, LL A, LL B, ll p) {//A^x%p=b s.t. (a,p) =1if (P <=) {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 <; ++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 ("NoSolution "); continue;} LL res = BSGS (C, X, K, z), if (res = =-1) puts ("No solution"), elseprintf ("%i64d\n", res + num);} return 0;}
POJ3243 EXT-BSGS algorithm