結果
| 問題 |
No.8030 ミラー・ラビン素数判定法のテスト
|
| ユーザー |
|
| 提出日時 | 2019-02-15 16:06:39 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,733 ms / 9,973 ms |
| コード長 | 2,576 bytes |
| コンパイル時間 | 789 ms |
| コンパイル使用メモリ | 70,016 KB |
| 実行使用メモリ | 5,248 KB |
| 最終ジャッジ日時 | 2024-11-16 23:12:53 |
| 合計ジャッジ時間 | 5,804 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 10 |
ソースコード
#include <iostream>
#include <vector>
using namespace std;
using U64 = uint64_t;
using S64 = int64_t;
//const S64 Primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
U64 ModMul(U64 a, U64 b, U64 modulus)
{
/*
{
S64 a2 = (S64)a;
if (a2 >= 0)
{
S64 b2 = (S64)b;
if (b2 >= 0)
{
if (!MulAsm(&a2, b2))
return (U64)a2 % modulus;
}
}
}
*/
a %= modulus; b %= modulus;
U64 result = 0;
while (a != 0)
{
if ((a & 1) != 0)
{
result += b;
if(result >= modulus) { result -= modulus; }
}
a >>= 1;
b <<= 1;
if(b >= modulus) { b -= modulus; }
}
return result;
}
U64 ModPow(U64 value, U64 exponent, U64 modulus)
{
U64 w = 1;
while (exponent > 0)
{
if ((exponent & 1) != 0)
w = ModMul(w, value, modulus);
value = ModMul(value, value, modulus);
exponent >>= 1;
}
return w;
}
bool is_prime(S64 n)
{
if (n <= 1)
return false;
if ((n & 1) == 0)
return n == 2;
for(U64 p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) {
if(n == p) { return true; }
if(n % p == 0) { return false; }
}
/*
if (n <= 1920000)
{
if (n == 3)
return true;
if (n % 6 != 1 && n % 6 != 5)
return false;
S64 m = n / 6 * 2 + (n % 6 == 1 ? 0 : 1);
size_t size;
const U8* primes_bin = GetPrimesBin(&size);
return (primes_bin[m / 8] & (1 << (m % 8))) != 0;
}
*/
// Miller-Rabin primality test.
/*
U64 enough;
if (n < 2047)
enough = 1;
else if (n < 1373653)
enough = 2;
else if (n < 25326001)
enough = 3;
else if (n < 3215031751)
enough = 4;
else if (n < 2152302898747)
enough = 5;
else if (n < 3474749660383)
enough = 6;
else if (n < 341550071728321)
enough = 7;
else if (n < 3825123056546413051)
enough = 9;
else
{
// n < 2^64 < 318665857834031151167461
enough = 12;
}
*/
{
vector<U64> witness = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
if(n < 1ULL<<32) { witness = {2, 7, 61}; }
U64 d = (U64)n - 1;
U64 s = 0;
while ((d & 1) == 0)
{
s++;
d >>= 1;
}
for (U64 a : witness)
{
if(a % n == 0) { return true; }
U64 x = ModPow(a, d, (U64)n);
U64 j;
if (x == 1 || x == (U64)n - 1)
continue;
bool probablyPrime = false;
for (j = 1; j < s; j++)
{
x = ModPow(x, 2, (U64)n);
if (x == (U64)n - 1)
{
probablyPrime = true;
break;
}
}
if (!probablyPrime)
return false;
}
return true;
}
}
int main(void) {
int n; scanf("%d", &n);
for(int loop=0; loop<n; ++loop) {
S64 x; scanf("%ld", &x);
printf("%ld %d\n", x, is_prime(x));
}
return 0;
}