import java.io.FileNotFoundException;
import java.util.Arrays;
public class Main {
new Main().run();
}
long pow(long a, long n) {
long ret = 1;
for (; n > 0; n >>= 1, a = a * a & (MOD - 1)) {
if (n % 2 == 1) {
ret = ret * a & (MOD - 1);
}
}
return ret;
}
void run() {
// a^x = b
for (int a = 3; a < MOD; a += 2) {
for (int b = 3; b < MOD; b += 2) {
int exact = -1;
for (int i = 0; i < MOD; ++i) {
if (pow(a, i) == b) {
exact = i;
break;
}
}
long x
= Math.
max(-1, discretelog
(a, b
)); if (x >= 0) {
System.
out.
println(a
+ "^" + x
+ "=" + b
+ "=" + pow
(a, x
)); }
if (x != exact) {
throw new AssertionError();
}
}
}
}
final int N = 5;
long MOD = 1L << N;
// a^x = b
// x = log_a (b)
// x = logb / loga
// return -1 when fail
long discretelog(long a, long b) {
if (a % 4 == 1 && b % 4 == 3)
return -1;
if (b == 1)
return 0;
if (a == b)
return 1;
if (a == 1) {
return -1;
}
if (a % 2 == 0 || b % 2 == 0)
throw new AssertionError();
if (b % 4 == 3) {
return 1 + discretelog(a, inv(a, MOD) * b % MOD);
}
if (a % 4 == 3) {
return 2 * discretelog(a * a % MOD, b) % MOD;
}
long loga = log(a);
long logb = log(b);
long g = gcd(loga, logb);
loga /= g;
logb /= g;
if (loga % 2 == 0) {
return -1;
}
return logb
* inv
(loga, MOD
) % (1L
<< (N
- Long.
numberOfTrailingZeros(a
- 1))); }
long log(long a) {
long ret = 0;
long x = a - 1;
// x^i == 0 (n < 2^i
for (int i = 1; i < 2 * N; ++i) {
int cnt2
= Long.
numberOfTrailingZeros(i
); long coe
= i
>> Long.
numberOfTrailingZeros(i
); long powx = 1;
for (int j = 0; j < i; ++j) {
powx = powx * x % MOD;
while (cnt2 > 0 && powx % 2 == 0) {
powx /= 2;
--cnt2;
}
}
ret += (i % 2 == 0 ? MOD - 1 : 1) * powx % MOD * inv(coe, MOD) % MOD;
ret %= MOD;
}
return ret;
}
// inv[0] := 1
public long inv(long a, long mod) {
a %= mod;
if (gcd(a, mod) != 1)
throw new AssertionError();
if (a < 0)
a += mod;
if (a == 0)
return 1;
long b = mod;
long p = 1, q = 0;
while (b > 0) {
long c = a / b;
long d;
d = a;
a = b;
b = d % b;
d = p;
p = q;
q = d - c * q;
}
return p < 0 ? p + mod : p;
}
long gcd(long a, long b) {
if (a < b) {
a ^= b;
b ^= a;
a ^= b;
}
if (b == 0) {
return a;
}
return gcd(a % b, b);
}
static void tr
(Object...
objects) { }
}
aW1wb3J0IGphdmEuaW8uRmlsZU5vdEZvdW5kRXhjZXB0aW9uOwppbXBvcnQgamF2YS51dGlsLkFycmF5czsKCnB1YmxpYyBjbGFzcyBNYWluIHsKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHRocm93cyBGaWxlTm90Rm91bmRFeGNlcHRpb24gewoJCW5ldyBNYWluKCkucnVuKCk7Cgl9CgoJbG9uZyBwb3cobG9uZyBhLCBsb25nIG4pIHsKCQlsb25nIHJldCA9IDE7CgkJZm9yICg7IG4gPiAwOyBuID4+PSAxLCBhID0gYSAqIGEgJiAoTU9EIC0gMSkpIHsKCQkJaWYgKG4gJSAyID09IDEpIHsKCQkJCXJldCA9IHJldCAqIGEgJiAoTU9EIC0gMSk7CgkJCX0KCQl9CgkJcmV0dXJuIHJldDsKCX0KCgl2b2lkIHJ1bigpIHsKCQkvLyBhXnggPSBiCgkJZm9yIChpbnQgYSA9IDM7IGEgPCBNT0Q7IGEgKz0gMikgewoJCQlmb3IgKGludCBiID0gMzsgYiA8IE1PRDsgYiArPSAyKSB7CgkJCQlpbnQgZXhhY3QgPSAtMTsKCQkJCWZvciAoaW50IGkgPSAwOyBpIDwgTU9EOyArK2kpIHsKCQkJCQlpZiAocG93KGEsIGkpID09IGIpIHsKCQkJCQkJZXhhY3QgPSBpOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCQlsb25nIHggPSBNYXRoLm1heCgtMSwgZGlzY3JldGVsb2coYSwgYikpOwoJCQkJaWYgKHggPj0gMCkgewoJCQkJCVN5c3RlbS5vdXQucHJpbnRsbihhICsgIl4iICsgeCArICI9IiArIGIgKyAiPSIgKyBwb3coYSwgeCkpOwoJCQkJfQoJCQkJaWYgKHggIT0gZXhhY3QpIHsKCQkJCQl0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoKTsKCQkJCX0KCQkJfQoJCX0KCX0KCglmaW5hbCBpbnQgTiA9IDU7Cglsb25nIE1PRCA9IDFMIDw8IE47CgoJLy8gYV54ID0gYgoJLy8geCA9IGxvZ19hIChiKQoJLy8geCA9IGxvZ2IgLyBsb2dhCgoJLy8gcmV0dXJuIC0xIHdoZW4gZmFpbAoJbG9uZyBkaXNjcmV0ZWxvZyhsb25nIGEsIGxvbmcgYikgewoJCWlmIChhICUgNCA9PSAxICYmIGIgJSA0ID09IDMpCgkJCXJldHVybiAtMTsKCQlpZiAoYiA9PSAxKQoJCQlyZXR1cm4gMDsKCQlpZiAoYSA9PSBiKQoJCQlyZXR1cm4gMTsKCQlpZiAoYSA9PSAxKSB7CgkJCXJldHVybiAtMTsKCQl9CgkJaWYgKGEgJSAyID09IDAgfHwgYiAlIDIgPT0gMCkKCQkJdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKCk7CgkJaWYgKGIgJSA0ID09IDMpIHsKCQkJcmV0dXJuIDEgKyBkaXNjcmV0ZWxvZyhhLCBpbnYoYSwgTU9EKSAqIGIgJSBNT0QpOwoJCX0KCQlpZiAoYSAlIDQgPT0gMykgewoJCQlyZXR1cm4gMiAqIGRpc2NyZXRlbG9nKGEgKiBhICUgTU9ELCBiKSAlIE1PRDsKCQl9CgkJbG9uZyBsb2dhID0gbG9nKGEpOwoJCWxvbmcgbG9nYiA9IGxvZyhiKTsKCQlsb25nIGcgPSBnY2QobG9nYSwgbG9nYik7CgkJbG9nYSAvPSBnOwoJCWxvZ2IgLz0gZzsKCQlpZiAobG9nYSAlIDIgPT0gMCkgewoJCQlyZXR1cm4gLTE7CgkJfQoJCXJldHVybiBsb2diICogaW52KGxvZ2EsIE1PRCkgJSAoMUwgPDwgKE4gLSBMb25nLm51bWJlck9mVHJhaWxpbmdaZXJvcyhhIC0gMSkpKTsKCX0KCglsb25nIGxvZyhsb25nIGEpIHsKCQlsb25nIHJldCA9IDA7CgkJbG9uZyB4ID0gYSAtIDE7CgkJLy8geF5pID09IDAgKG4gPCAyXmkKCQlmb3IgKGludCBpID0gMTsgaSA8IDIgKiBOOyArK2kpIHsKCQkJaW50IGNudDIgPSBMb25nLm51bWJlck9mVHJhaWxpbmdaZXJvcyhpKTsKCQkJbG9uZyBjb2UgPSBpID4+IExvbmcubnVtYmVyT2ZUcmFpbGluZ1plcm9zKGkpOwoJCQlsb25nIHBvd3ggPSAxOwoJCQlmb3IgKGludCBqID0gMDsgaiA8IGk7ICsraikgewoJCQkJcG93eCA9IHBvd3ggKiB4ICUgTU9EOwoJCQkJd2hpbGUgKGNudDIgPiAwICYmIHBvd3ggJSAyID09IDApIHsKCQkJCQlwb3d4IC89IDI7CgkJCQkJLS1jbnQyOwoJCQkJfQoJCQl9CgkJCXJldCArPSAoaSAlIDIgPT0gMCA/IE1PRCAtIDEgOiAxKSAqIHBvd3ggJSBNT0QgKiBpbnYoY29lLCBNT0QpICUgTU9EOwoJCQlyZXQgJT0gTU9EOwoJCX0KCQlyZXR1cm4gcmV0OwoJfQoKCS8vIGludlswXSA6PSAxCglwdWJsaWMgbG9uZyBpbnYobG9uZyBhLCBsb25nIG1vZCkgewoJCWEgJT0gbW9kOwoJCWlmIChnY2QoYSwgbW9kKSAhPSAxKQoJCQl0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoKTsKCQlpZiAoYSA8IDApCgkJCWEgKz0gbW9kOwoJCWlmIChhID09IDApCgkJCXJldHVybiAxOwoJCWxvbmcgYiA9IG1vZDsKCQlsb25nIHAgPSAxLCBxID0gMDsKCQl3aGlsZSAoYiA+IDApIHsKCQkJbG9uZyBjID0gYSAvIGI7CgkJCWxvbmcgZDsKCQkJZCA9IGE7CgkJCWEgPSBiOwoJCQliID0gZCAlIGI7CgkJCWQgPSBwOwoJCQlwID0gcTsKCQkJcSA9IGQgLSBjICogcTsKCQl9CgkJcmV0dXJuIHAgPCAwID8gcCArIG1vZCA6IHA7Cgl9CgoJbG9uZyBnY2QobG9uZyBhLCBsb25nIGIpIHsKCQlpZiAoYSA8IGIpIHsKCQkJYSBePSBiOwoJCQliIF49IGE7CgkJCWEgXj0gYjsKCQl9CgkJaWYgKGIgPT0gMCkgewoJCQlyZXR1cm4gYTsKCQl9CgkJcmV0dXJuIGdjZChhICUgYiwgYik7Cgl9CgoJc3RhdGljIHZvaWQgdHIoT2JqZWN0Li4uIG9iamVjdHMpIHsKCQlTeXN0ZW0ub3V0LnByaW50bG4oQXJyYXlzLmRlZXBUb1N0cmluZyhvYmplY3RzKSk7Cgl9Cn0K