結果
問題 | No.3030 ミラー・ラビン素数判定法のテスト |
ユーザー | iwkjosec |
提出日時 | 2019-05-18 01:02:02 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 9,570 bytes |
コンパイル時間 | 1,058 ms |
コンパイル使用メモリ | 112,744 KB |
実行使用メモリ | 46,048 KB |
最終ジャッジ日時 | 2024-11-18 16:41:43 |
合計ジャッジ時間 | 46,194 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | WA | - |
testcase_01 | AC | 26 ms
23,856 KB |
testcase_02 | AC | 26 ms
25,876 KB |
testcase_03 | AC | 28 ms
23,860 KB |
testcase_04 | TLE | - |
testcase_05 | TLE | - |
testcase_06 | AC | 4,109 ms
25,768 KB |
testcase_07 | AC | 3,996 ms
23,736 KB |
testcase_08 | AC | 3,989 ms
21,940 KB |
testcase_09 | TLE | - |
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc) Copyright (C) Microsoft Corporation. All rights reserved.
ソースコード
using System; using System.Collections.Generic; using System.Linq; using static System.Console; using static System.Math; using System.Numerics; class Program { static void Main() { var n = long.Parse(ReadLine()); for (int i = 0; i < n; i++) { var x = long.Parse(ReadLine()); WriteLine(x.ToString() + " " + (MillerRabin(x) ? "1" : "0")); } } static uint[] l = new uint[] { 2, 325, 9375, 28178, 450775, 9780504, 1795265022 }; static bool MillerRabin(long n) { if (n < 2) return false; if (n % 2 == 0) return n == 2; var d = n - 1; var s = 0; while (d % 2 == 0) { s++; d >>= 1; } var dd = (UInt128)d; var nn = (UInt128)n; for (int i = 0; i < l.Length && l[i] < n; i++) { var a = l[i]; var c = true; var x = UInt128.ModPow(a, dd, nn); if (x == 1) c = false; for (int r = 0; r < s; r++) { if (x == nn - 1) c = false; x = x * x % nn; } if (c) return false; } return true; } } struct UInt128 { public ulong low; public ulong high; public static UInt128 operator +(UInt128 l, UInt128 r)//片方にもう片方足して返すのとin引数にして新しいインスタンス返すのどっちがいいんだろう { var s = new UInt128 { low = l.low + r.low, high = l.high + r.high }; if (s.low < l.low) s.high++; return s; } public static UInt128 operator -(UInt128 l, UInt128 r) { var s = new UInt128 { low = l.low - r.low, high = l.high - r.high }; if (s.low > l.low) s.high--; return s; } public static UInt128 operator *(UInt128 l, UInt128 r)//導出は n bit * n bit -> 2n bit ができないとき 上位ビット下位ビットに分割して考える { var h = l.low * r.high + l.high * r.low; var lll = l.low & 0xFFFFFFFF; var llh = l.low >> 32; var rll = r.low & 0xFFFFFFFF; var rlh = r.low >> 32; var a = lll * rll; var b = lll * rlh + llh * rll; var c = llh * rlh; if (b < lll * rlh) c += 1UL << 32; var lo = a + (b << 32); var hi = c + (b >> 32); if (lo < a) hi++; hi += h; return new UInt128 { low = lo, high = hi }; } public static UInt128 operator /(UInt128 l, UInt128 r)//rが奇数になるまでlr両方に右シフトしてよい//アルゴが思いつかないから繰り返し2倍法 { if (r == 0) throw new DivideByZeroException(); while ((r.low & 1) == 0) { r >>= 1; l >>= 1; } var m = (UInt128)1; var q = (UInt128)0; while (r <= l) { r <<= 1; m <<= 1; } while (1 < m) { r >>= 1; m >>= 1; if (l >= r) { l -= r; q |= m; } } return q; } public static UInt128 operator %(UInt128 l, UInt128 r)//DivRem作った方がいいのか { return l - l / r * r; } public static UInt128 operator &(UInt128 l, UInt128 r) { return new UInt128 { low = l.low & r.low, high = l.high & r.high }; } public static UInt128 operator |(UInt128 l, UInt128 r) { return new UInt128 { low = l.low | r.low, high = l.high | r.high }; } public static UInt128 operator ^(UInt128 l, UInt128 r) { return new UInt128 { low = l.low ^ r.low, high = l.high ^ r.high }; } public static UInt128 operator <<(UInt128 l, int r) { r &= 0x7F; if (r >= 64) { l.high = l.low << r - 64; l.low = 0; } else { l.high <<= r; l.high |= l.low >> 64 - r; l.low <<= r; } return l; } public static UInt128 operator >>(UInt128 l, int r) { r &= 0x7F; if (r >= 64) { l.low = l.high >> r - 64; l.high = 0; } else { l.low >>= r; l.low |= l.high << 64 - r; l.high >>= r; } return l; } public static bool operator ==(UInt128 l, UInt128 r) { return l.low == r.low && l.high == r.high; } public static bool operator !=(UInt128 l, UInt128 r) { return l.low != r.low || l.high != r.high; } public static bool operator >(UInt128 l, UInt128 r) { return l.high > r.high || l.low > r.low; } public static bool operator <(UInt128 l, UInt128 r) { return l.high < r.high || l.low < r.low; } public static bool operator >=(UInt128 l, UInt128 r) { if (l.high > r.high) return true; if (l.high == r.high && l.low >= r.low) return true; return false; } public static bool operator <=(UInt128 l, UInt128 r) { if (l.high < r.high) return true; if (l.high == r.high && l.low <= r.low) return true; return false; } public static UInt128 operator ~(UInt128 v) { v.low = ~v.low; v.high = ~v.high; return v; } public static UInt128 operator +(UInt128 v) { return v; } public static UInt128 operator ++(UInt128 v) { return v + 1; } public static UInt128 operator --(UInt128 v) { return v - 1; } public static explicit operator UInt128(sbyte v) { return new UInt128 { low = (ulong)v }; } public static implicit operator UInt128(byte v) { return new UInt128 { low = v }; } public static explicit operator UInt128(short v) { return new UInt128 { low = (ulong)v }; } public static implicit operator UInt128(ushort v) { return new UInt128 { low = v }; } public static explicit operator UInt128(int v) { return new UInt128 { low = (ulong)v }; } public static implicit operator UInt128(uint v) { return new UInt128 { low = v }; } public static explicit operator UInt128(long v) { return new UInt128 { low = (ulong)v }; } public static implicit operator UInt128(ulong v) { return new UInt128 { low = v }; } public static explicit operator UInt128(BigInteger v) { var ret = new UInt128 { low = (ulong)v }; v >>= 64; ret.high = (ulong)v; return ret; } public static explicit operator sbyte(UInt128 v) { return (sbyte)(v.low & 0x7F); } public static explicit operator byte(UInt128 v) { return (byte)v.low; } public static explicit operator short(UInt128 v) { return (short)(v.low & 0x7FFF); } public static explicit operator ushort(UInt128 v) { return (ushort)v.low; } public static explicit operator int(UInt128 v) { return (int)v.low & int.MaxValue; } public static explicit operator uint(UInt128 v) { return (uint)v.low; } public static explicit operator long(UInt128 v) { return (long)v.low & long.MaxValue; } public static explicit operator ulong(UInt128 v) { return v.low; } public static implicit operator BigInteger(UInt128 v) { return (new BigInteger(v.high) << 64) | v.low; } public static UInt128 ModPow(UInt128 x, UInt128 n, UInt128 m) { var res = (UInt128)1; while (n != 0) { if ((n & 1) == 1) res = res * x % m; x = x * x % m; n >>= 1; } return res; } public static UInt128 Parse(string s)// -0を許容して -nはovfとして扱いたい 要はuint,ulongと挙動をそろえたい { if (s is null) throw new ArgumentNullException(); s = s.Trim(); if (s.Length == 0) throw new FormatException(); if (s[0] == '+') { if (s.Length == 1) throw new FormatException(); else s = s.Substring(1); } var a = 0; for (int i = 0; i < s.Length; i++) { if (s[i] != '0') { a = i; break; } } s = s.Substring(a == s.Length - 1 ? a - 1 : a); if (s.Length > 39) throw new FormatException(); for (int i = 0; i < s.Length; i++) { if ((uint)(s[i] - '0') > '9') throw new FormatException(); } if (s.Length == 39 && s.CompareTo("340282366920938463463374607431768211456") != 1) throw new OverflowException(); var ret = new UInt128(); for (int i = 0; i < s.Length; i++) { ret *= 10; ret += (uint)(s[i] - '0'); } return ret; } public override string ToString() { if (this == 0) return "0"; var a = this; var ret = new List<char>(40); while (a != 0) { ret.Add((char)((int)(a % 10) + '0')); a /= 10; } ret.Reverse(); return new string(ret.ToArray()); } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } }