結果
問題 | No.3030 ミラー・ラビン素数判定法のテスト |
ユーザー | MotSak |
提出日時 | 2023-05-20 11:00:46 |
言語 | C# (.NET 8.0.203) |
結果 |
AC
|
実行時間 | 247 ms / 9,973 ms |
コード長 | 6,397 bytes |
コンパイル時間 | 15,684 ms |
コンパイル使用メモリ | 167,084 KB |
実行使用メモリ | 187,628 KB |
最終ジャッジ日時 | 2024-06-01 06:01:50 |
合計ジャッジ時間 | 17,077 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 44 ms
23,040 KB |
testcase_01 | AC | 43 ms
22,912 KB |
testcase_02 | AC | 42 ms
22,784 KB |
testcase_03 | AC | 42 ms
22,912 KB |
testcase_04 | AC | 170 ms
26,984 KB |
testcase_05 | AC | 186 ms
26,880 KB |
testcase_06 | AC | 151 ms
27,132 KB |
testcase_07 | AC | 149 ms
26,624 KB |
testcase_08 | AC | 149 ms
26,752 KB |
testcase_09 | AC | 247 ms
187,628 KB |
コンパイルメッセージ
復元対象のプロジェクトを決定しています... /home/judge/data/code/main.csproj を復元しました (95 ms)。 MSBuild のバージョン 17.9.6+a4ecab324 (.NET) main -> /home/judge/data/code/bin/Release/net8.0/main.dll main -> /home/judge/data/code/bin/Release/net8.0/publish/
ソースコード
using System; using System.IO; using System.Numerics; namespace PrimalityTest { class Program { static void Main() { Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }); var n = FastIStream.Long(); for (int i = 0; i < n; i++) { var x = (ulong)FastIStream.Long(); Console.WriteLine(x.ToString() + " " + (x.IsPrime() ? "1" : "0")); } Console.Out.Flush(); } } static class FastIStream { static readonly Stream str = Console.OpenStandardInput(); const int size = 1024; static readonly byte[] buffer = new byte[size]; static int ptr = size; static byte Read() { if (ptr == size) { str.Read(buffer, 0, size); ptr = 0; } return buffer[ptr++]; } public static long Long() { var c = Read(); while (c < 0x21) { c = Read(); } var n = false; if (c == '-') { n = true; c = Read(); } var ret = 0L; while (c > 0x20) { ret = ret * 10 + c - '0'; c = Read(); } return n ? -ret : ret; } } static class PrimalityTestExtension { public static bool IsPrime(this ulong n) { if (n == 2) { return true; } if (n < 2 || (n & 1) == 0) { return false; } var mont = new U64Mont(n); return mont.BailliePSWTest(); } private class U64Mont { private ulong N { get; } private ulong Ninv { get; } private ulong Nhalf { get; } private ulong R { get; } private ulong Rneg { get; } private ulong D { get; } private int S { get; } public U64Mont(ulong n) { N = n; Ninv = n; for (int i = 0; i < 5; ++i) { Ninv *= 2 - n * Ninv; } Nhalf = (n >> 1) + 1; R = (0 - n) % n; Rneg = n - R; S = BitOperations.TrailingZeroCount(n - 1); D = n - 1 >> S; } public bool BailliePSWTest() { return MillerRabinTestBase2() && LucasTest(); } public bool MillerRabinTestBase2() { ulong tR = PowR(Add(R, R), D); if (tR == R || tR == Rneg) { return true; } for (int j = 1; j < S; ++j) { tR = MR(tR, tR); if (tR == Rneg) { return true; } } return false; } public bool LucasTest() { ulong n = N; long d = 5; for (int i = 0; i < 64; ++i) { if (Jacobi(d, n) == -1) { break; } if (i == 32 && IntSqrtU64Remain(n) == 0) { return false; } if ((i & 1) == 0) { d = -(d + 2); } else { d = 2 - d; } } ulong qm = AR((d < 0) ? ((((ulong)(1 - d)) >> 2) % n) : (n - (((ulong)(d - 1)) >> 2) % n)); ulong k = (n + 1) << BitOperations.LeadingZeroCount(n + 1); ulong um = R; ulong vm = R; ulong qn = qm; ulong dm = AR((d < 0) ? (n - (ulong)-d % n) : ((ulong)d % n)); for (k <<= 1; k > 0; k <<= 1) { um = MR(um, vm); vm = Sub(MR(vm, vm), Add(qn, qn)); qn = MR(qn, qn); if ((k >> 63) != 0) { ulong uu = Div2(Add(um, vm)); vm = Div2(Add(MR(dm, um), vm)); um = uu; qn = MR(qn, qm); } } if (um == 0 || vm == 0) { return true; } ulong x = (n + 1) & (~n); for (x >>= 1; x > 0; x >>= 1) { um = MR(um, vm); vm = Sub(MR(vm, vm), Add(qn, qn)); if (vm == 0) { return true; } qn = MR(qn, qn); } return false; } // a + b (mod n) private ulong Add(ulong a, ulong b) { return AddOverflow(a, b, out ulong t) || t >= N ? t - N : t; } // a - b (mod n) private ulong Sub(ulong a, ulong b) { return a < b ? N + a - b : a - b; } // a / 2 (mod n) private ulong Div2(ulong a) { return (a & 1) == 0 ? a >> 1 : (a >> 1) + Nhalf; } // (ar * br) / r (mod n) private ulong MR(ulong ar, ulong br) { return Sub(BigMul(ar, br, out ulong t), BigMul(t * Ninv, N, out _)); } // a * r (mod n) private ulong AR(ulong a) { ulong t = R; ulong ar = (a & 1) != 0 ? R : 0; a >>= 1; while (a != 0) { t = Add(t, t); if ((a & 1) != 0) { ar = Add(ar, t); } a >>= 1; } return ar; } // ((ar / r) ** k) * r (mod n) private ulong PowR(ulong ar, ulong k) { ulong tr = (k & 1) != 0 ? ar : R; k >>= 1; while (k != 0) { ar = MR(ar, ar); if ((k & 1) != 0) { tr = MR(tr, ar); } k >>= 1; } return tr; } private static bool AddOverflow(ulong lhs, ulong rhs, out ulong result) { return lhs > (result = lhs + rhs); } private static ulong BigMul(ulong a, ulong b, out ulong low) { return Math.BigMul(a, b, out low); } private static ulong IntSqrtU64(ulong x, out ulong remain) { const int BITS = 64; BigInteger tmpRemain = x; BigInteger tmpAnswer = (((BigInteger)0x0000000000000000UL) << 64) | 0x4000000000000000UL; BigInteger maskLead = (((BigInteger)0xfffffffffffffffeUL) << 64) | 0x0000000000000000UL; BigInteger maskCarry = (((BigInteger)0x0000000000000001UL) << 64) | 0x0000000000000000UL; BigInteger maskTail = (((BigInteger)0x0000000000000000UL) << 64) | 0xffffffffffffffffUL; for (uint i = 0; i < (BITS >> 1); ++i) { BigInteger next = ((tmpAnswer << 1) & maskLead) | (tmpAnswer & maskTail); if (tmpRemain >= tmpAnswer) { tmpRemain -= tmpAnswer; tmpAnswer = next + maskCarry; } else { tmpAnswer = next; } tmpRemain <<= 2; } remain = (ulong)(tmpRemain >> BITS); return (ulong)(tmpAnswer >> BITS); } private static ulong IntSqrtU64Remain(ulong x) { IntSqrtU64(x, out ulong remain); return remain; } private static int Jacobi(long sa, ulong n) { ulong a; int j; if (sa >= 0) { a = (ulong)sa; j = 1; } else { a = (ulong)-sa; j = ((n & 3) == 3) ? -1 : 1; } while (a > 0) { int ba = BitOperations.TrailingZeroCount(a); a >>= ba; if (((n & 7) == 3 || (n & 7) == 5) && (ba & 1) != 0) { j = -j; } if ((a & n & 3) == 3) { j = -j; } ulong t = n; n = a; a = t; a %= n; if (a > (n >> 1)) { a = n - a; if ((n & 3) == 3) { j = -j; } } } return (n == 1) ? j : 0; } } } }