#include <cstdio>
#include <iostream>
using i64 = long long;
using u32 = unsigned;
using u64 = unsigned long long;
/*
// 1 でも動作する
struct FastDiv {
FastDiv() {}
FastDiv(u64 n) : m(n) {
s = (n == 1) ? 0 : 64 + std::__lg(n - 1);
x = ((__uint128_t(1) << s) + n - 1) / n;
}
friend u64 operator / (u64 n, FastDiv d) { return __uint128_t(n) * d.x >> d.s; }
friend u64 operator % (u64 n, FastDiv d) { return n - n / d * d.m; }
u64 m, x; int s;
};
*/
// 1 は動作しない
struct FastDiv {
FastDiv() {}
FastDiv(u64 n) : m(n) {
s = std::__lg(n - 1);
x = ((__uint128_t(1) << (s + 64)) + n - 1) / n;
}
friend u64 operator / (u64 n, FastDiv d) {
return (__uint128_t(n) * d.x >> d.s) >> 64;
}
friend u64 operator % (u64 n, FastDiv d) { return n - n / d * d.m; }
u64 m, x; int s;
};
inline u64 mod64_32_small(u64 a, u32 b) {
u32 q, r;
__asm__ (
"divl\t%4"
: "=a"(q), "=d"(r)
: "0"(u32(a)), "1"(u32(a >> 32)), "rm"(b)
);
return r;
}
int fact_slow(int n, int mod) {
int ret = 1;
for (int i = 1; i <= n; ++i) ret = i64(ret) * i % mod;
return ret;
}
int fact_slow_asm(int n, int mod) {
int ret = 1;
for (int i = 1; i <= n; ++i) ret = mod64_32_small(u64(ret) * i, mod);
return ret;
}
int fact_fast(int n, int mod) {
auto fd = FastDiv(mod);
int ret = 1;
for (int i = 1; i <= n; ++i) ret = i64(ret) * i % fd;
return ret;
}
int main() {
int mod; scanf("%d", &mod);
clock_t beg = clock();
int a1 = fact_slow(mod - 1, mod);
clock_t t1 = clock();
int a2 = fact_slow_asm(mod - 1, mod);
clock_t t2 = clock();
int a3 = fact_fast(mod - 1, mod);
clock_t t3 = clock();
printf("%d %.3f\n", a1, double(t1 - beg) / CLOCKS_PER_SEC);
printf("%d %.3f\n", a2, double(t2 - t1) / CLOCKS_PER_SEC);
printf("%d %.3f\n", a3, double(t3 - t2) / CLOCKS_PER_SEC);
return 0;
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKdXNpbmcgaTY0ID0gbG9uZyBsb25nOwp1c2luZyB1MzIgPSB1bnNpZ25lZDsKdXNpbmcgdTY0ID0gdW5zaWduZWQgbG9uZyBsb25nOwoKLyoKLy8gMSDjgafjgoLli5XkvZzjgZnjgosKc3RydWN0IEZhc3REaXYgewogIEZhc3REaXYoKSB7fQogIEZhc3REaXYodTY0IG4pIDogbShuKSB7CiAgICBzID0gKG4gPT0gMSkgPyAwIDogNjQgKyBzdGQ6Ol9fbGcobiAtIDEpOwogICAgeCA9ICgoX191aW50MTI4X3QoMSkgPDwgcykgKyBuIC0gMSkgLyBuOwogIH0KICBmcmllbmQgdTY0IG9wZXJhdG9yIC8gKHU2NCBuLCBGYXN0RGl2IGQpIHsgcmV0dXJuIF9fdWludDEyOF90KG4pICogZC54ID4+IGQuczsgfQogIGZyaWVuZCB1NjQgb3BlcmF0b3IgJSAodTY0IG4sIEZhc3REaXYgZCkgeyByZXR1cm4gbiAtIG4gLyBkICogZC5tOyB9CiAgdTY0IG0sIHg7IGludCBzOwp9OwoqLwoKLy8gMSDjga/li5XkvZzjgZfjgarjgYQKc3RydWN0IEZhc3REaXYgewogIEZhc3REaXYoKSB7fQogIEZhc3REaXYodTY0IG4pIDogbShuKSB7CiAgICBzID0gc3RkOjpfX2xnKG4gLSAxKTsKICAgIHggPSAoKF9fdWludDEyOF90KDEpIDw8IChzICsgNjQpKSArIG4gLSAxKSAvIG47CiAgfQogIGZyaWVuZCB1NjQgb3BlcmF0b3IgLyAodTY0IG4sIEZhc3REaXYgZCkgeyAKICAgIHJldHVybiAoX191aW50MTI4X3QobikgKiBkLnggPj4gZC5zKSA+PiA2NDsgCiAgfQogIGZyaWVuZCB1NjQgb3BlcmF0b3IgJSAodTY0IG4sIEZhc3REaXYgZCkgeyByZXR1cm4gbiAtIG4gLyBkICogZC5tOyB9CiAgdTY0IG0sIHg7IGludCBzOwp9OwoKaW5saW5lIHU2NCBtb2Q2NF8zMl9zbWFsbCh1NjQgYSwgdTMyIGIpIHsKICB1MzIgcSwgcjsKICBfX2FzbV9fICgKICAgICJkaXZsXHQlNCIKICAgIDogIj1hIihxKSwgIj1kIihyKQogICAgOiAiMCIodTMyKGEpKSwgIjEiKHUzMihhID4+IDMyKSksICJybSIoYikKICApOwogIHJldHVybiByOwp9CgppbnQgZmFjdF9zbG93KGludCBuLCBpbnQgbW9kKSB7CiAgaW50IHJldCA9IDE7CiAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgKytpKSByZXQgPSBpNjQocmV0KSAqIGkgJSBtb2Q7CiAgcmV0dXJuIHJldDsKfQoKaW50IGZhY3Rfc2xvd19hc20oaW50IG4sIGludCBtb2QpIHsKICBpbnQgcmV0ID0gMTsKICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHJldCA9IG1vZDY0XzMyX3NtYWxsKHU2NChyZXQpICogaSwgbW9kKTsKICByZXR1cm4gcmV0Owp9CgppbnQgZmFjdF9mYXN0KGludCBuLCBpbnQgbW9kKSB7CiAgYXV0byBmZCA9IEZhc3REaXYobW9kKTsKICBpbnQgcmV0ID0gMTsKICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHJldCA9IGk2NChyZXQpICogaSAlIGZkOwogIHJldHVybiByZXQ7Cn0KCmludCBtYWluKCkgewogIGludCBtb2Q7IHNjYW5mKCIlZCIsICZtb2QpOwogIGNsb2NrX3QgYmVnID0gY2xvY2soKTsKICBpbnQgYTEgPSBmYWN0X3Nsb3cobW9kIC0gMSwgbW9kKTsKICBjbG9ja190IHQxID0gY2xvY2soKTsKICBpbnQgYTIgPSBmYWN0X3Nsb3dfYXNtKG1vZCAtIDEsIG1vZCk7CiAgY2xvY2tfdCB0MiA9IGNsb2NrKCk7CiAgaW50IGEzID0gZmFjdF9mYXN0KG1vZCAtIDEsIG1vZCk7CiAgY2xvY2tfdCB0MyA9IGNsb2NrKCk7CiAgcHJpbnRmKCIlZCAlLjNmXG4iLCBhMSwgZG91YmxlKHQxIC0gYmVnKSAvIENMT0NLU19QRVJfU0VDKTsKICBwcmludGYoIiVkICUuM2ZcbiIsIGEyLCBkb3VibGUodDIgLSB0MSkgLyBDTE9DS1NfUEVSX1NFQyk7CiAgcHJpbnRmKCIlZCAlLjNmXG4iLCBhMywgZG91YmxlKHQzIC0gdDIpIC8gQ0xPQ0tTX1BFUl9TRUMpOwogIHJldHVybiAwOwp9