Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 310 Solved: 178
Description
小Y发现,数学中有一个很有趣的式子: X^Y mod Z = K 给出X、Y、Z,我们都知道如何很快的计算K。但是如果给出X、Z、K,你是否知道如何快速的计算Y呢?
Input
本题由多组数据(不超过20组),每组测试数据包含一行三个整数X、Z、K(0 <= X, Z, K <= 109)。 输入文件一行由三个空格隔开的0结尾。
Output
对于每组数据:如果无解则输出一行No Solution,否则输出一行一个整数Y(0 <= Y < Z),使得其满足XY mod Z = K,如果有多个解输出最小的一个Y。
Sample Input
5 58 33
2 4 3
0 0 0
Sample Output
9
No Solution
HINT
Source
ghy
就是一个exBSGS套一下,裸题,BZOJ里map水过,poj过不了,要t
#include<algorithm>
#include<iostream>
#include<cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <iostream>
using namespace std;
map <long long,long long> mp;
long long gcd( long long x, long long y ) { return y == 0 ? x : gcd ( y, x % y ); }
long long fast_pow( long long x, long long y, long long mod ) {
long long tmp = 1, BASE = x;
while( y ) {
if( y & 1 ) tmp = ( tmp * BASE ) % mod;
y >>= 1;
BASE = ( BASE * BASE ) % mod;
}
return tmp;
}
long long exBSGS( long long a, long long b, long long c) {
if ( b == 1 ) return 0;
long long k = 0, tmp, d = 1;
while( ( tmp = gcd( a, c ) ) != 1 ){
if( b % tmp ) return -1;
k++; b /= tmp; c /= tmp; d = d * ( a / tmp ) % c;
if( b == d ) return k;
}
mp.clear();
long long m = ceil( sqrt( ( double )c ) );long long am = fast_pow( a, m, c );
long long ans = b; mp[ans] = 0;
long long tem = 1;
for( register int i = 1; i <= m; i++ ) {
ans = ans * a % c;
mp[ans] = i;
}
for (register int i = 1; i <= m; i++ ) {
tem = tem * am % c;
if( mp[tem] ) return i * m - mp[tem] + k;
}
return -1;
}
int main() { long long a, c, b;
while( scanf( "%lld%lld%lld", &a, &c, &b ) != EOF ) {
if( a == 0 && c == 0 && b == 0 ) break;
long long ans = exBSGS( a % c, b % c, c );
if( ans != -1 ) printf( "%lld\n", ans );
else printf( "No Solution\n" );
}
return 0;
}