結果

問題 No.3030 ミラー・ラビン素数判定法のテスト
ユーザー kaoru muratakaoru murata
提出日時 2021-09-01 16:46:40
言語 C
(gcc 12.3.0)
結果
WA  
実行時間 -
コード長 2,013 bytes
コンパイル時間 361 ms
コンパイル使用メモリ 32,000 KB
実行使用メモリ 14,016 KB
最終ジャッジ日時 2024-05-05 20:50:04
合計ジャッジ時間 11,932 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 WA -
testcase_01 WA -
testcase_02 WA -
testcase_03 TLE -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>

typedef int64_t i64;
typedef __int128_t i128;
typedef uint64_t u64;
typedef __uint128_t u128;

typedef u64 m64;

u64 mul_inv(u64 n) {
  u64 x = 1;
  for (int i = 6; i > 0; --i) {
    x = x * (2 - x * n);
  }
  return x;
}
m64 calc_mod(u64 m) {
  return m;
}
m64 calc_inv(u64 m) {
  return mul_inv(calc_mod(m));
}
m64 calc_r2(u64 m) {
  return -(u128)(calc_mod(m)) % calc_mod(m);
}
m64 MR(u128 x, m64 mod, m64 inv) {
  m64 y = (u64)(x >> 64) - (u64)(((u128)((u64)x * inv) * mod) >> 64);
  return (i64)y < 0 ? y + mod : y;
}
m64 toM64(u64 w, m64 mod, m64 inv, m64 r2) { return MR((u128)w * r2, mod, inv); }
u64 fromM64(m64 x, m64 mod, m64 inv) { return MR((u128)x, mod, inv); }
m64 addmod(m64 x, m64 y, m64 mod) {
  return (x + y >= mod) ? x + y - mod: x + y;
}
m64 submod(m64 x, m64 y, m64 mod) {
  return (i64)(x - y) < 0 ? x - y + mod : x - y;
}
m64 mulmod(m64 x, m64 y, m64 mod, m64 inv) {
  return MR((u128)x * y, mod, inv);
}
m64 powmod(m64 x, int i, m64 mod, m64 inv, m64 r2) {
  m64 ret = toM64(1, mod, inv, r2);
  for (; i; i >>= 1) {
    if (i & 1) ret = mulmod(ret, x, mod, inv);
    x = mulmod(x, x, mod, inv);
  }
  return ret;
}

bool is_prime(u64 N) {
  if (N < 2 || N % 6 % 4 != 1) return (N | 1) == 3;
  int s = __builtin_ctzll(N - 1);
  u64 d = (N - 1) >> s;
  u64 as[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
  m64 inv = calc_inv(N);
  m64 r2 = calc_r2(N);
  m64 e = toM64(1, N, inv, r2);
  m64 f = toM64(N - 1, N, inv, r2);
  for (int i = 0; i < 7; i++) {
    m64 a = toM64(as[i], N, inv, r2);
    m64 p = powmod(a, d, N, inv, r2);
    if (a == 0 || p == e || p == f) continue;
    for (int i = s - 1; p != f && i >= 0; --i) p = powmod(p, 2, N, inv, r2);
    if (p != f) return false;
  }
  return true;
}

int main() {
  int n; scanf("%d", &n);
  for (int i = 0; i < n; i++) {
    u64 x; scanf("%lu", &x);
    if (is_prime(x)) {
      printf("%d\n", 1);
    }
    else {
      printf("%d\n", 0);
    }
  }
  return 0;
}
0