結果

問題 No.3030 ミラー・ラビン素数判定法のテスト
ユーザー JashinchanJashinchan
提出日時 2022-10-05 16:11:17
言語 C
(gcc 12.3.0)
結果
TLE  
実行時間 -
コード長 2,306 bytes
コンパイル時間 1,371 ms
コンパイル使用メモリ 32,008 KB
実行使用メモリ 8,760 KB
最終ジャッジ日時 2023-08-30 07:07:01
合計ジャッジ時間 13,145 ms
ジャッジサーバーID
(参考情報)
judge13 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 0 ms
4,376 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 3 ms
4,376 KB
testcase_03 AC 6 ms
4,376 KB
testcase_04 TLE -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.c: 関数 ‘in_u128’ 内:
main.c:11:16: 警告: 関数 ‘getchar_unlocked’ の暗黙的な宣言です [-Wimplicit-function-declaration]
   11 |     while (c = getchar_unlocked(), c < 48 || c > 57)
      |                ^~~~~~~~~~~~~~~~
main.c: 関数 ‘out_u128’ 内:
main.c:24:5: 警告: 関数 ‘putchar_unlocked’ の暗黙的な宣言です [-Wimplicit-function-declaration]
   24 |     putchar_unlocked(x - x / 10 * 10 + 48);
      |     ^~~~~~~~~~~~~~~~

ソースコード

diff #

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

typedef __uint128_t u128;

u128 in_u128(void)
{
    u128 c, x = 0;
    while (c = getchar_unlocked(), c < 48 || c > 57)
        ;
    while (47 < c && c < 58)
    {
        x = x * 10 + c - 48;
        c = getchar_unlocked();
    }
    return x;
}
void out_u128(u128 x)
{
    if (x >= 10)
        out_u128(x / 10);
    putchar_unlocked(x - x / 10 * 10 + 48);
}
void NL(void)
{
    putchar_unlocked('\n');
}
void SP(void)
{
    putchar_unlocked(' ');
}

u128 mul_mod_128(u128 a, u128 b, u128 m)
{
    u128 al = a & 0xffffffffffffffffull, ah = a >> 64;
    u128 bl = b & 0xffffffffffffffffull, bh = b >> 64;
    u128 ret = ah * bh % m;
    for (int _ = 0; _ < 64; ++_)
        ret = (ret << 1) % m;
    ret = (ret + al * bh + bl * ah) % m;
    for (int _ = 0; _ < 64; ++_)
        ret = (ret << 1) % m;
    ret = (ret + al * bl) % m;
    return ret;
}

u128 square_mod_128(u128 a, u128 m)
{
    return mul_mod_128(a, a, m);
}

u128 pow_mod_128(u128 a, u128 k, u128 m)
{
    return k ? mul_mod_128(pow_mod_128(square_mod_128(a, m), k >> 1, m), (k & 1 ? a : 1), m) : 1;
}

bool miller_rabin_128(u128 a, int s, u128 d, u128 n)
{
    u128 x = pow_mod_128(a, d, n);
    if (x == 1)
        return true;
    for (int r = 0; r < s; ++r)
    {
        if (x == n - 1)
            return true;
        x = square_mod_128(x, n);
    }
    return false;
}

bool is_prime(u128 n)
{
    u128 tiny_primes[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
    if (n <= 100)
    {
        for (size_t i = 0; i < 25; ++i)
        {
            if (n == tiny_primes[i])
            {
                return true;
            }
        }
        return false;
    }
    if (!(n & 1))
    {
        return false;
    }
    u128 d = n - 1;
    int s = 0;
    while (!(d & 1))
    {
        d >>= 1;
        ++s;
    }
    for (size_t i = 0; i < 25; ++i)
    {
        if (!miller_rabin_128(tiny_primes[i], s, d, n))
        {
            return false;
        }
    }
    return true;
}

int main(void)
{
    int Q;
    scanf("%d", &Q);
    while (Q--)
    {
        u128 x = in_u128();
        out_u128(x), SP(), putchar_unlocked(is_prime(x) ? '1' : '0');
        NL();
    }
    return 0;
}
0