Clever Y
Time Limit: 5000MS |
|
Memory Limit: 65536K |
Total Submissions: 7259 |
|
Accepted: 1795 |
Description
Little Y finds there is a very interesting formula in mathematics:
XY MoD Z = K
Given X, Y, Z, we all know the figure of out K fast. However, given X,Z,K, could you figure outY fast?
Input
Input data consists of no more than test cases. For each test case, there would is only one line containing 3 integers
X,
Z,
K (0≤
x , Z, K ≤109).
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 332 4 30 0 0
Sample Output
9No Solution
Source
POJ monthly--2007.07.08, Guo, Huayang
Test Instructions:
X^y%z=k, calculates the minimum Y value of the equation.
Problem Solving Ideas:
Extending the BSGS algorithm, the common BSGS algorithm requires that the C value of the A^X≡B (mod c) be prime, because the equation has a solution requirement of gcd (A,C) | B, only if C is a prime number, it must be established. And this question does not say that C must be prime. So it is necessary to use the EXT-BSGS algorithm, see this algorithm is also understood for a long time. Online reference to explain the algorithm is not much, find information for a long time. Summarize the algorithm yourself.
First must be ordinary bsgs, General BSGS algorithm explanation: Click to open the link
We know that the common BSGS algorithm can handle the case of C as prime number, which is guaranteed gcd (A,C) | B, so we just have to make sure this happens. How can this happen? We can make gcd (a,c) = 1 so that it is guaranteed to be divisible by B.
How can I get (a,c) =1? We can always let C, divided by (a,c). When C has removed all the a,c's conventions, (A,C) must be equal to 1. Note that the C value is the transformed C value (a,c), i.e. C[i]=c[i]/(A,c[i-1]).
To ensure that the equation is true, we must divide each part of the equation by this value. We have been circulating C/(A,C), b/(A,c), and the value of a^x is not a A/(A,C) This should be noted. In addition, we consider taking a divide (a,c) from A^x, at this time: a^x=a/(a,c) *a^ (x-1).
Our loop operation ends at (a,c) = 1, so a^x=d*a^ (x-cnt) After CNT operation, since we have removed CNT a altogether. Each time we loop we also update the D value, which is the value of each A/(a,c) multiplied by the value of the last loop. That is, the loop is: d=d*a/(a,c). So we d≠a^cnt here. Pay attention to this point.
After we have done this, the equation becomes d*a^ (x′) ≡b′ (mod c′), x′=x-cnt. As soon as we solve the x′ of the equation, we can find the value of X, x=x′+cnt. Because A*d≡b*d (mod c*d) is equivalent to A≡b (mod C). So the solution we've obtained is equivalent.
And in this case we (a,c) = 1, then we can directly use the ordinary BSGS solution.
Equivalent to a^ (i*m) *d*a^j≡b (mod C). We can find the right J-value.
In the end, we have an important problem not solved, we look at an example: 49^x≡0 (mod 343), it is obvious that x=0, but if based on the above method, the result will be 2. The answer here is obviously wrong, and here we will find the answer if it is smaller than CNT, and then the CNT will become an incorrect value, so we can try to enumerate all the x values less than CNT, to see if the X value exists. If present, return the X value directly, no more bsgs steps. Because c each time the minimum elimination factor is 2, so CNT maximum is log (c), we enumerate [0,log (c)] value is OK.
AC Code:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include < algorithm>using namespace Std;const int maxn = 1000010;typedef long long ll;bool HASH[MAXN]; LL P[MAXN]; ll Var[maxn];void insert_x (ll N,ll v) {int x=v%maxn; while (HASH[X]&&VAR[X]!=V) {x + +; if (X==MAXN) x=0; } if (!hash[x]) {p[x]=n; Var[x]=v; Hash[x]=true; }}ll find_x (LL v) {int x=v%maxn; while (HASH[X]&&VAR[X]!=V) {x + +; if (X==MAXN) x=0; } if (Hash[x]) return p[x]; return-1;} ll GCD (ll A,ll b) {if (b==0) return A; return gcd (b,a%b);} ll EXGCD (ll a,ll b,ll &x,ll &y) {if (b==0) {x=1;y=0; return A; } LL R=EXGCD (b,a%b,x,y); LL t=x; X=y; Y=t-a/b*y; return r;} ll Bsgs (ll a,ll b,ll C) {ll n=1; for (int i=0;i<110;i++) {//Enumerate all x values less than log (C) if (n==b%c) return i; n=n*a%c; } int cnt=0; LL Res=1; LL DivisOR=GCD (A,C); while (divisor!=1) {//Extinction (A,C) All conventions number if (B%divisor) {return-1; } c/=divisor; B/=divisor; res=res*a/divisor%c; DIVISOR=GCD (A,C); cnt++; } LL M=ceil (sqrt (c*1.0)); LL temp=1; for (int i=0;i<m;i++) {insert_x (i,temp); temp=temp*a%c; } for (int i=0;i<m;i++) {LL x, y; LL R=EXGCD (res,c,x,y); X=x*b; x= (x%c+c)%c; LL coordinate=find_x (x); if (coordinate!=-1) {return (I*M+COORDINATE+CNT); } res=res*temp%c; } return-1;} int main () {LL x,z,k; while (scanf ("%lld%lld%lld", &x,&z,&k)!=eof) {if (! x&&! z&&! K) break; memset (hash,false,sizeof (hash)); memset (Var,-1,sizeof (Var)); memset (P,-1,sizeof (p)); LL coordinate=bsgs (x,k,z); if (coordinate==-1) printf ("No solution\n"); else printf ("%lld\n", coordinate); } return 0;}
Copyright NOTICE: This article is the original blogger articles, reproduced please indicate the source.
"Ext-bsgs Algorithm for discrete logarithm" POJ Clever Y 3243