結果
問題 | No.3030 ミラー・ラビン素数判定法のテスト |
ユーザー | Jashinchan |
提出日時 | 2022-08-27 19:41:42 |
言語 | C (gcc 12.3.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 5,062 bytes |
コンパイル時間 | 1,079 ms |
コンパイル使用メモリ | 35,416 KB |
実行使用メモリ | 6,824 KB |
最終ジャッジ日時 | 2024-10-14 16:10:52 |
合計ジャッジ時間 | 1,669 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,816 KB |
testcase_01 | AC | 1 ms
6,816 KB |
testcase_02 | AC | 1 ms
6,820 KB |
testcase_03 | AC | 1 ms
6,820 KB |
testcase_04 | WA | - |
testcase_05 | WA | - |
testcase_06 | WA | - |
testcase_07 | WA | - |
testcase_08 | WA | - |
testcase_09 | WA | - |
コンパイルメッセージ
main.c: In function 'in_u128': main.c:128:14: warning: implicit declaration of function 'getchar_unlocked' [-Wimplicit-function-declaration] 128 | char c = getchar_unlocked(); | ^~~~~~~~~~~~~~~~ main.c: In function 'out_u128': main.c:143:5: warning: implicit declaration of function 'putchar_unlocked' [-Wimplicit-function-declaration] 143 | putchar_unlocked(x % 10 + '0'); | ^~~~~~~~~~~~~~~~
ソースコード
#include <stdint.h> #include <stdio.h> typedef int64_t i64; typedef uint64_t u64; typedef __int128_t i128; typedef __uint128_t u128; typedef struct { u128 lo, hi; } u256; typedef struct { u256 lo, hi; } u512; u256 make_u256(u128 lo, u128 hi) { u256 ret; ret.lo = lo; ret.hi = hi; return ret; } u512 make_u512(u256 lo, u256 hi) { u512 ret; ret.lo = lo; ret.hi = hi; return ret; } const u128 MSB128 = ((u128)0x8000000000000000ull) << 64; u256 mul128(u128 a, u128 b) { u64 a_hi = a >> 64, a_lo = (u64)a; u64 b_hi = b >> 64, b_lo = (u64)b; u128 p01 = (u128)(a_lo) * b_lo; u128 p12 = (u128)(a_hi) * b_lo + (u64)(p01 >> 64); u64 t_hi = p12 >> 64, t_lo = p12; p12 = (u128)a_lo * b_hi + t_lo; u128 p23 = (u128)(a_hi) * b_hi + (u64)(p12 >> 64) + t_hi; return make_u256((u64)p01 | (p12 << 64), p23); } u256 add256(u256 a, u256 b) { u256 ret; ret.hi = a.hi + b.hi; ret.lo = a.lo + b.lo; if (ret.lo < a.lo || ret.lo < b.lo) ++ret.hi; return ret; } u256 sub256(u256 a, u256 b) { u256 ret; ret.hi = a.hi - b.hi; ret.lo = a.lo - b.lo; if (ret.lo > a.lo) --ret.hi; return ret; } int cmp256(u256 a, u256 b) { if (a.hi == b.hi && a.lo == b.lo) return 0; else if ((a.hi > b.hi) || ((a.hi == b.hi) && (a.lo > b.lo))) return 1; else return -1; } u256 shl256(u256 a) { u256 ret; a.hi <<= 1; a.hi |= ((a.lo & MSB128) ? 1 : 0); a.lo <<= 1; ret.hi = a.hi; ret.lo = a.lo; return ret; } u512 shl512(u512 a) { u512 ret; a.hi = shl256(a.hi); a.hi.lo |= ((a.lo.hi & MSB128) ? 1 : 0); a.lo = shl256(a.lo); ret.hi = a.hi; ret.lo = a.lo; return ret; } u256 mod256(u256 a, u256 b) { u512 p; p.hi = make_u256(0, 0), p.lo = a; for (unsigned i = 0; i < 256; ++i) { p = shl512(p); if (cmp256(p.hi, b) >= 0) { p.hi = sub256(p.hi, b); p.lo.lo |= 1; } } return p.hi; } u128 pow_u128(u128 a, u128 t, u128 mod) { u128 r = 1; for (; t; t >>= 1, a = mod256(mul128(a, a), make_u256(mod, 0)).lo) if (t & 1) r = mod256(mul128(r, a), make_u256(mod, 0)).lo; return r; } u128 in_u128() { u128 k = 0; char c = getchar_unlocked(); while (c < '0' || c > '9') c = getchar_unlocked(); while (c >= '0' && c <= '9') { k = (k << 1) + (k << 3) + (c ^ 48); c = getchar_unlocked(); } return k; } void out_u128(u128 x) { if (x > 9) out_u128(x / 10); putchar_unlocked(x % 10 + '0'); } u128 n_mr128(u128 mod) { return mod; } u128 ni_mr128(u128 mod) { u128 ni = mod; for (int _ = 0; _ < 6; ++_) ni *= 2 - ni * mod; return ni; } u128 reduce(u256 z, u128 n, u128 ni) { u128 y = z.hi - mul128(z.lo * ni, n).hi; return (y & MSB128) ? y + n : y; } u128 mul_mr128(u128 a, u128 b, u128 n, u128 ni) { return reduce(mul128(a, b), n, ni); } u128 r_mr128(u128 mod) { return (~mod + 1) % mod; } u128 r2_mr128(u128 mod, u128 ni) { u128 r2 = (~mod+ 1) % mod; for (int _ = 0; _ < 4; ++_) if ((r2 <<= 1) >= mod) r2 -= mod; for (int _ = 0; _ < 5; ++_) r2 = mul_mr128(r2, r2, mod, ni); } u128 add_mr128(u128 a, u128 b, u128 n) { return (a < n - b) ? a + b : sub256(add256(make_u256(a, 0), make_u256(b, 0)), make_u256(n, 0)).lo; } u128 sub_mr128(u128 a, u128 b, u128 n) { return (a < b) ? sub256(add256(make_u256(a, 0), make_u256(n, 0)), make_u256(b, 0)).lo : a - b; } u128 pow_mr128(u128 a, u128 k, u128 n, u128 ni, u128 r) { u128 ret = r; while (k > 0) { if (k & 1) ret = mul_mr128(ret, a, n, ni); a = mul_mr128(a, a, n, ni); k >>= 1; } return ret; } u128 to_mr128(u128 a, u128 n, u128 ni, u128 r2) { return reduce(mul128(n, r2), n, ni); } u128 from_mr128(u128 a, u128 n, u128 ni) { return reduce(make_u256(a, 0), n, ni); } int is_prime(u128 n) { static const u128 bases[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; if (n == 1 || ((!(n & 1)) && n > 2)) return 0; for (int i = 0; i < 12; ++i) if (n % bases[i] == 0) return n == bases[i]; u128 d = n - 1; u128 x, y; u128 ni = ni_mr128(n); u128 r = r_mr128(n); u128 r2 = r2_mr128(n, ni); u128 rev = to_mr128(n - 1, n, ni, r2); int e = 0; while (~d & 1) d >>= 1, ++e; for (int i = 0; i < 12; ++i) { u128 p = to_mr128(bases[i], n, ni, r2); x = pow_mr128(p, d, n, ni, r); for (int t = 0; t < e && x > 1; ++t) { y = mul_mr128(x, x, n, ni); if (y == r && x != rev) return 0; x = y; } if (x != 1) return 0; } return 1; } int main(void) { u128 q = in_u128(); while (q--) { u128 x = in_u128(); out_u128(x); putchar_unlocked(' '); if (is_prime(x)) putchar_unlocked('1'); else putchar_unlocked('0'); putchar_unlocked('\n'); } return 0; }