結果
| 問題 |
No.8030 ミラー・ラビン素数判定法のテスト
|
| ユーザー |
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 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 6 WA * 1 TLE * 3 |
コンパイルメッセージ
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();
}
}
iwkjosec