private static StaticModInt <T>[] CalcurateSumE() { int g = InternalMath.PrimitiveRoot((int)default(T).Mod); int cnt2 = InternalBit.BSF(default(T).Mod - 1); var e = new StaticModInt <T>(g).Pow((default(T).Mod - 1) >> cnt2); var ie = e.Inv(); var sumE = new StaticModInt <T> [cnt2 - 2]; // es[i]^(2^(2+i)) == 1 Span <StaticModInt <T> > es = stackalloc StaticModInt <T> [cnt2 - 1]; Span <StaticModInt <T> > ies = stackalloc StaticModInt <T> [cnt2 - 1]; for (int i = es.Length - 1; i >= 0; i--) { // e^(2^(2+i)) == 1 es[i] = e; ies[i] = ie; e *= e; ie *= ie; } var now = StaticModInt <T> .Raw(1); for (int i = 0; i < sumE.Length; i++) { sumE[i] = es[i] * now; now *= ies[i]; } return(sumE); }
public static void Calculate(Span <StaticModInt <T> > a) { var n = a.Length; var h = InternalMath.CeilPow2(n); for (int ph = 1; ph <= h; ph++) { // ブロックサイズの半分 int w = 1 << (ph - 1); // ブロック数 int p = 1 << (h - ph); var now = StaticModInt <T> .Raw(1); // 各ブロックの s 段目 for (int s = 0; s < w; s++) { int offset = s << (h - ph + 1); for (int i = 0; i < p; i++) { var l = a[i + offset]; var r = a[i + offset + p] * now; a[i + offset] = l + r; a[i + offset + p] = l - r; } now *= sumE[InternalBit.BSF(~(uint)s)]; } } }
public static void CalculateInv(Span <StaticModInt <T> > a) { var n = a.Length; var h = InternalMath.CeilPow2(n); for (int ph = h; ph >= 1; ph--) { // ブロックサイズの半分 int w = 1 << (ph - 1); // ブロック数 int p = 1 << (h - ph); var iNow = StaticModInt <T> .Raw(1); // 各ブロックの s 段目 for (int s = 0; s < w; s++) { int offset = s << (h - ph + 1); for (int i = 0; i < p; i++) { var l = a[i + offset]; var r = a[i + offset + p]; a[i + offset] = l + r; a[i + offset + p] = StaticModInt <T> .Raw( unchecked ((int)((ulong)(default(T).Mod + l.Value - r.Value) * (ulong)iNow.Value % default(T).Mod))); } iNow *= sumIE[InternalBit.BSF(~(uint)s)]; } } }
public void SafeMod() { var preds = new List <long>(); for (int i = 0; i <= 100; i++) { preds.Add(i); preds.Add(-i); preds.Add(i); preds.Add(long.MinValue + i); preds.Add(long.MaxValue - i); } foreach (var a in preds) { foreach (var b in preds) { if (b <= 0) { continue; } var ans = (long)((new BigInteger(a) % b + b) % b); InternalMath.SafeMod(a, b).Should().Be(ans); } } }
public void PrimitiveRootTest() { for (int i = 0; i < 1000; i++) { int x = int.MaxValue - i; if (!InternalMath.IsPrime(x)) { continue; } MathUtil.IsPrimitiveRoot(x, mods[x].PrimitiveRoot()).Should().BeTrue(); } }
public void PrimitiveRootTemplateTest() { MathUtil.IsPrimitiveRoot(2, InternalMath.PrimitiveRoot <Mod2>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(3, InternalMath.PrimitiveRoot <Mod3>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(5, InternalMath.PrimitiveRoot <Mod5>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(7, InternalMath.PrimitiveRoot <Mod7>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(11, InternalMath.PrimitiveRoot <Mod11>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(998244353, InternalMath.PrimitiveRoot <Mod998244353>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(1000000007, InternalMath.PrimitiveRoot <Mod1000000007>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(469762049, InternalMath.PrimitiveRoot <Mod469762049>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(167772161, InternalMath.PrimitiveRoot <Mod167772161>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(754974721, InternalMath.PrimitiveRoot <Mod754974721>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(324013369, InternalMath.PrimitiveRoot <Mod324013369>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(831143041, InternalMath.PrimitiveRoot <Mod831143041>()).Should().BeTrue(); MathUtil.IsPrimitiveRoot(1685283601, InternalMath.PrimitiveRoot <Mod1685283601>()).Should().BeTrue(); }
public void InvGcdBound() { var pred = new List <long>(); for (int i = 0; i <= 10; i++) { pred.Add(i); pred.Add(-i); pred.Add(long.MinValue + i); pred.Add(long.MaxValue - i); pred.Add(long.MinValue / 2 + i); pred.Add(long.MinValue / 2 - i); pred.Add(long.MaxValue / 2 + i); pred.Add(long.MaxValue / 2 - i); pred.Add(long.MinValue / 3 + i); pred.Add(long.MinValue / 3 - i); pred.Add(long.MaxValue / 3 + i); pred.Add(long.MaxValue / 3 - i); } pred.Add(998244353); pred.Add(1_000_000_007); pred.Add(1_000_000_009); pred.Add(-998244353); pred.Add(-1_000_000_007); pred.Add(-1_000_000_009); foreach (var a in pred) { foreach (var b in pred) { if (b <= 0) { continue; } long a2 = InternalMath.SafeMod(a, b); (long first, long second) = InternalMath.InvGCD(a, b); var g = Gcd(a2, b); first.Should().Be(g); second.Should().BeGreaterOrEqualTo(0); (b / first).Should().BeGreaterOrEqualTo(second); ((long)(new BigInteger(second) * a2 % b)).Should().Be(g % b); } } }
public void IsPrime() { InternalMath.IsPrime(121).Should().BeFalse(); InternalMath.IsPrime(11 * 13).Should().BeFalse(); InternalMath.IsPrime(1_000_000_007).Should().BeTrue(); InternalMath.IsPrime(1_000_000_008).Should().BeFalse(); InternalMath.IsPrime(1_000_000_009).Should().BeTrue(); for (int i = 0; i <= 10000; i++) { InternalMath.IsPrime(i).Should().Be(IsPrimeNaive(i)); } for (int i = 0; i <= 10000; i++) { int x = int.MaxValue - i; InternalMath.IsPrime(x).Should().Be(IsPrimeNaive(x)); } }
private static StaticModInt <T>[] CalcurateSumIE() { int g = InternalMath.PrimitiveRoot <T>(); int cnt2 = InternalBit.BSF(default(T).Mod - 1); var e = new StaticModInt <T>(g).Pow((default(T).Mod - 1) >> cnt2); var ie = e.Inv(); var sumIE = new StaticModInt <T> [30]; // es[i]^(2^(2+i)) == 1 Span <StaticModInt <T> > es = #if !NETCOREAPP3_0_OR_GREATER new #else stackalloc #endif StaticModInt <T> [cnt2 - 1]; Span <StaticModInt <T> > ies = #if !NETCOREAPP3_0_OR_GREATER new #else stackalloc #endif StaticModInt <T> [cnt2 - 1]; for (int i = es.Length - 1; i >= 0; i--) { // e^(2^(2+i)) == 1 es[i] = e; ies[i] = ie; e *= e; ie *= ie; } var now = StaticModInt <T> .Raw(1); for (int i = 0; i <= cnt2 - 2; i++) { sumIE[i] = ies[i] * now; now *= es[i]; } return(sumIE); }
public void PrimitiveRootTestNaive() { for (int m = 2; m <= 10000; m++) { if (!InternalMath.IsPrime(m)) { continue; } //int n = InternalMath.PrimitiveRoot(m); int n = mods[m].PrimitiveRoot(); n.Should().BeGreaterOrEqualTo(1); m.Should().BeGreaterThan(n); int x = 1; for (int i = 1; i <= m - 2; i++) { x = (int)((long)x * n % m); // x == n^i x.Should().NotBe(1); } x = (int)((long)x * n % m); x.Should().Be(1); } }