-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathPON.cs
108 lines (90 loc) · 2.66 KB
/
PON.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System;
// https://www.spoj.com/problems/PON/ #math #primes
// Determines if a number is (probably) prime.
public static class PON
{
private static readonly Random _rand = new Random();
public static bool Solve(ulong n)
=> MillerRabinTest(n, witnessCount: 10);
// https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
private static bool MillerRabinTest(ulong n, int witnessCount)
{
if (n < 2) return false;
if (n == 2 || n == 3) return true;
if ((n & 1) == 0) return false;
ulong d = n - 1;
int r = 0;
while ((d & 1) == 0)
{
d >>= 1;
++r;
}
while (witnessCount-- > 0)
{
if (!MillerRabinWitness(n, d, r))
return false; // composite
}
return true; // probably prime
}
private static bool MillerRabinWitness(ulong n, ulong d, int r)
{
ulong a = (ulong)_rand.Next() % (n - 3) + 2;
ulong x = ModularPow(a, d, n);
if (x == 1 || x == n - 1)
return true;
while (--r > 0)
{
x = ModularMultiply(x, x, n);
if (x == n - 1)
return true;
}
return false; // composite
}
// https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/
private static ulong ModularMultiply(ulong a, ulong b, ulong modulus)
{
ulong result = 0;
a = a % modulus;
while (b > 0)
{
if ((b & 1) == 1)
{
result = (result + a) % modulus;
}
a = (a << 1) % modulus;
b >>= 1;
}
return result % modulus;
}
// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
// https://stackoverflow.com/a/383596
// https://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method
private static ulong ModularPow(ulong @base, ulong exponent, ulong modulus)
{
ulong result = 1;
@base = @base % modulus;
while (exponent != 0)
{
if ((exponent & 1) == 1)
{
result = ModularMultiply(result, @base, modulus);
}
@base = ModularMultiply(@base, @base, modulus);
exponent >>= 1;
}
return result;
}
}
public static class Program
{
private static void Main()
{
int remainingTestCases = int.Parse(Console.ReadLine());
while (remainingTestCases-- > 0)
{
ulong n = ulong.Parse(Console.ReadLine());
Console.WriteLine(
PON.Solve(n) ? "YES" : "NO");
}
}
}