結果
問題 | No.3030 ミラー・ラビン素数判定法のテスト |
ユーザー | iwkjosec |
提出日時 | 2020-09-13 06:34:46 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 14,374 bytes |
コンパイル時間 | 1,143 ms |
コンパイル使用メモリ | 119,960 KB |
実行使用メモリ | 29,268 KB |
最終ジャッジ日時 | 2024-11-18 18:26:22 |
合計ジャッジ時間 | 34,157 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | WA | - |
testcase_01 | AC | 26 ms
23,728 KB |
testcase_02 | AC | 28 ms
23,732 KB |
testcase_03 | AC | 27 ms
23,844 KB |
testcase_04 | AC | 6,953 ms
23,704 KB |
testcase_05 | AC | 6,725 ms
25,504 KB |
testcase_06 | AC | 2,601 ms
23,824 KB |
testcase_07 | AC | 2,531 ms
23,604 KB |
testcase_08 | AC | 2,528 ms
23,604 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 System.Numerics; 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; if (!c) break; x = x * x % nn; } if (c) return false; } return true; } } public struct UInt128 { public ulong low; public ulong high; public static UInt128 MaxValue => new UInt128 { low = ulong.MaxValue, high = ulong.MaxValue }; public static UInt128 MinValue => 0; public UInt128(ulong h, ulong l) { low = l; high = h; } 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)//l + ~r + 1 だと思うけどこれでも正しそう { 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 left, UInt128 right) { if (left < right) return 0; //var n = Min(TZC(left), TZC(right)); //left >>= n; //right >>= n; //var m = LZC(right) - LZC(left); var m = LZC(right); right <<= m; var q = (UInt128)0; while (m >= 0) { if (left >= right) { q |= (UInt128)1 << m; left -= right; } right >>= 1; m--; } return q; } // public static int TZC(UInt128 v) //{ // if (v.low == 0) return BitOperations.TrailingZeroCount(v.high) + 64; // else return BitOperations.TrailingZeroCount(v.low); // } public static int LZC(UInt128 v) { if (v.high == 0) return LeadingZeroCount(v.low) + 64; else return LeadingZeroCount(v.high); } public static int LeadingZeroCount(uint value) { // Unguarded fallback contract is 0->31, BSR contract is 0->undefined if (value == 0) { return 32; } return 31 ^ Log2SoftwareFallback(value); } public static int LeadingZeroCount(ulong value) { uint hi = (uint)(value >> 32); if (hi == 0) { return 32 + LeadingZeroCount((uint)value); } return LeadingZeroCount(hi); } private static int Log2SoftwareFallback(uint value) { // No AggressiveInlining due to large method size // Has conventional contract 0->0 (Log(0) is undefined) // Fill trailing zeros with ones, eg 00010010 becomes 00011111 value |= value >> 01; value |= value >> 02; value |= value >> 04; value |= value >> 08; value |= value >> 16; // uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check return Log2DeBruijn[(int)((value * 0x07C4ACDDu) >> 27)]; } private static ReadOnlySpan<byte> Log2DeBruijn => new byte[32] { 00, 09, 01, 10, 13, 21, 02, 29, 11, 14, 16, 18, 22, 25, 03, 30, 08, 12, 20, 28, 15, 17, 24, 07, 19, 27, 23, 06, 26, 05, 04, 31 }; public static UInt128 operator %(UInt128 left, UInt128 right) { return left - (left / right) * right; } 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; if (r != 0) 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; if (r != 0) 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) { if (l.high > r.high) return true; if (l.high < r.high) return false; return l.low > r.low; } public static bool operator <(UInt128 l, UInt128 r) { if (l.high < r.high) return true; if (l.high > r.high) return false; return 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 = -1; for (int i = 0; i < s.Length; i++) { if (s[i] != '0') { a = i; break; } } if (a == -1) return new UInt128 { low = 0, high = 0 }; s = s.Substring(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 += (UInt128)(s[i] - '0'); } return ret; } //適当 本当にこれでいいのかわからん public static bool TryParse(string s, out UInt128 result) { try { result = Parse(s); } catch (Exception) { result = 0; return false; } return true; } public static UInt128 FastParse(string s) { var ret = new UInt128(); for (int i = 0; i < s.Length; i++) { ret *= 10; ret += (UInt128)(s[i] - '0'); } return ret; } public override string ToString() // https://source.dot.net/#System.Private.CoreLib/shared/System/Number.Formatting.cs UInt32ToDecStr { if (this == 0) return "0"; var a = this; var ret = new char[a.CountDisits()]; for (int i = ret.Length - 1; i >= 0; i--) { var d = a / 10; ret[i] = (char)(a - (d * 10) + '0'); a = d; } return new string(ret); } static UInt128 e30; static UInt128() { e30 = FastParse("1000000000000000000000000000000"); } public int CountDisits()//if elseの所分割したら速い?プリミティブ型と違って除算が激遅だから展開した方が速い? { int digits = 1; ulong part; if (this >= 10000000000000000000UL) { if (this >= e30) { part = (ulong)(this / e30); digits += 30; } else { part = (ulong)(this / 10000000000000000000UL); digits += 19; } } else { if (this >= 10000000000UL) { part = (ulong)(this / 10000000000UL); digits += 10; } else { part = (ulong)this; } } if (part < 10) { // no-op } else if (part < 100) { digits++; } else if (part < 1000) { digits += 2; } else if (part < 10000) { digits += 3; } else if (part < 100000) { digits += 4; } else if (part < 1000000) { digits += 5; } else if (part < 10000000) { digits += 6; } else if (part < 100000000) { digits += 7; } else if (part < 1000000000) { digits += 8; } else if (part < 10000000000) { digits += 9; } else { digits += 10; } return digits; } //Obsolate public override bool Equals(object obj) { return base.Equals(obj); } //Obsolate //Dictionaryが参照する・・・? public override int GetHashCode() { return base.GetHashCode(); } }