public static long FloorSum(long n, long m, long a, long b) { Contract.Assert(0 <= n && n < (1L << 32)); Contract.Assert(1 <= m && m < (1L << 32)); var nn = (ulong)n; var mm = (ulong)m; ulong aa, bb; ulong ans = 0; if (a < 0) { var a2 = (ulong)InternalMath.SafeMod(a, m); ans -= nn * (nn - 1) / 2 * ((a2 - (ulong)a) / mm); aa = a2; } else { aa = (ulong)a; } if (b < 0) { var b2 = (ulong)InternalMath.SafeMod(b, m); ans -= nn * ((b2 - (ulong)b) / mm); bb = b2; } else { bb = (ulong)b; } return((long)(ans + InternalMath.FloorSumUnsigned(nn, mm, aa, bb))); }
/// <summary> /// <paramref name="x"/>y≡1(mod <paramref name="m"/>) なる y のうち、0≤y<<paramref name="m"/> を満たすものを返します。 /// </summary> /// <remarks> /// <para>制約: gcd(<paramref name="x"/>,<paramref name="m"/>)=1, 1≤<paramref name="m"/></para> /// <para>計算量: O(log<paramref name="m"/>)</para> /// </remarks> public static long InvMod(long x, int m) { Debug.Assert(1 <= m); var(g, res) = InternalMath.InvGCD(x, m); Debug.Assert(g == 1); return(res); }
public static long InvMod(long x, long m) { Contract.Assert(1 <= m, reason: $"1 <= {nameof(m)}"); var(g, res) = InternalMath.InvGCD(x, m); Contract.Assert(g == 1, reason: $"gcd({nameof(x)}, {nameof(m)}) must be 1."); return(res); }
/// <summary> /// 長さ <paramref name="n"/> の数列 a を持つ <see cref="Segtree{TValue, TOp}"/> クラスの新しいインスタンスを作ります。初期値は <see cref="TOp.Identity"/> です。 /// </summary> /// <remarks> /// <para>制約: 0≤<paramref name="n"/>≤10^8</para> /// <para>計算量: O(<paramref name="n"/>)</para> /// </remarks> /// <param name="n">配列の長さ</param> public Segtree(int n) { AssertMonoid(op.Identity); Length = n; log = InternalMath.CeilPow2(n); size = 1 << log; d = new TValue[2 * size]; Array.Fill(d, op.Identity); }
private static long FloorSumNative(long n, long m, long a, long b) { long sum = 0; for (long i = 0; i < n; i++) { long z = a * i + b; sum += (z - InternalMath.SafeMod(z, m)) / m; } return(sum); }
static long Native(long x, long n, int mod) { uint mmod = (uint)mod; ulong y = (ulong)InternalMath.SafeMod(x, mmod); ulong z = 1 % mmod; for (long i = 0; i < n; i++) { z = (z * y) % mmod; } return((long)z); }
/// <summary> /// 長さ <paramref name="n"/> の数列 a を持つ <see cref="LazySegtree{TValue, TOp}"/> クラスの新しいインスタンスを作ります。初期値は <see cref="TOp.Identity"/> です。 /// </summary> /// <remarks> /// <para>制約: 0≤<paramref name="n"/>≤10^8</para> /// <para>計算量: O(<paramref name="n"/>)</para> /// </remarks> /// <param name="n">配列の長さ</param> public LazySegtree(int n) { AssertMonoid(op.Identity); AssertFIdentity(op.Identity); AssertF(op.FIdentity, op.Identity, op.Identity); Length = n; log = InternalMath.CeilPow2(n); size = 1 << log; d = new TValue[2 * size]; lz = new F[size]; Array.Fill(d, op.Identity); Array.Fill(lz, op.FIdentity); }
public void IsPrimitiveRootTest() { for (int m = 2; m <= 500; m++) { if (!InternalMath.IsPrime(m)) { continue; } for (int g = 1; g < m; g++) { MathUtil.IsPrimitiveRoot(m, g).Should().Be(IsPrimitiveRootNative(m, g)); } } }
/// <summary> /// 同じ長さ n の配列 <paramref name="r"/>, <paramref name="m"/> について、x≡<paramref name="r"/>[i] (mod <paramref name="m"/>[i]),∀i∈{0,1,⋯,n−1} を解きます。 /// </summary> /// <remarks> /// <para>制約: |<paramref name="r"/>|=|<paramref name="m"/>|, 1≤<paramref name="m"/>[i], lcm(m[i]) が ll に収まる</para> /// <para>計算量: O(nloglcm(<paramref name="m"/>))</para> /// </remarks> /// <returns>答えは(存在するならば) y,z(0≤y<z=lcm(<paramref name="m"/>[i])) を用いて x≡y(mod z) の形で書ける。答えがない場合は(0,0)、n=0 の時は(0,1)、それ以外の場合は(y,z)。</returns> public static (long y, long m) CRT(long[] r, long[] m) { Contract.Assert(r.Length == m.Length, reason: $"Length of {nameof(r)} and {nameof(m)} must be same."); long r0 = 0, m0 = 1; for (int i = 0; i < m.Length; i++) { Contract.Assert(1 <= m[i], reason: $"All of {nameof(m)} must be greater or equal 1."); long r1 = InternalMath.SafeMod(r[i], m[i]); long m1 = m[i]; if (m0 < m1) { (r0, r1) = (r1, r0); (m0, m1) = (m1, m0); } if (m0 % m1 == 0) { if (r0 % m1 != r1) { return(0, 0); } continue; } var(g, im) = InternalMath.InvGCD(m0, m1); long u1 = (m1 / g); if ((r1 - r0) % g != 0) { return(0, 0); } long x = (r1 - r0) / g % u1 * im % u1; r0 += x * m0; m0 *= u1; if (r0 < 0) { r0 += m0; } } return(r0, m0); }
/// <summary> /// 同じ長さ n の配列 <paramref name="r"/>, <paramref name="m"/> について、x≡<paramref name="r"/>[i] (mod <paramref name="m"/>[i]),∀i∈{0,1,⋯,n−1} を解きます。 /// </summary> /// <remarks> /// <para>制約: |<paramref name="r"/>|=|<paramref name="m"/>|, 1≤<paramref name="m"/>[i], lcm(m[i]) が ll に収まる</para> /// <para>計算量: O(nloglcm(<paramref name="m"/>))</para> /// </remarks> /// <returns>答えは(存在するならば) y,z(0≤y<z=lcm(<paramref name="m"/>[i])) を用いて x≡y(mod z) の形で書ける。答えがない場合は(0,0)、n=0 の時は(0,1)、それ以外の場合は(y,z)。</returns> public static (long, long) CRT(long[] r, long[] m) { Debug.Assert(r.Length == m.Length); long r0 = 0, m0 = 1; for (int i = 0; i < m.Length; i++) { Debug.Assert(1 <= m[i]); long r1 = InternalMath.SafeMod(r[i], m[i]); long m1 = m[i]; if (m0 < m1) { (r0, r1) = (r1, r0); (m0, m1) = (m1, m0); } if (m0 % m1 == 0) { if (r0 % m1 != r1) { return(0, 0); } continue; } var(g, im) = InternalMath.InvGCD(m0, m1); long u1 = (m1 / g); if ((r1 - r0) % g != 0) { return(0, 0); } long x = (r1 - r0) / g % u1 * im % u1; r0 += x * m0; m0 *= u1; if (r0 < 0) { r0 += m0; } } return(r0, m0); }
/// <summary> /// <paramref name="x"/>^<paramref name="n"/> mod <paramref name="m"/> を返します。 /// </summary> /// <remarks> /// <para>制約: 0≤<paramref name="n"/>, 1≤<paramref name="m"/></para> /// <para>計算量: O(log<paramref name="n"/>)</para> /// </remarks> public static long PowMod(long x, long n, int m) { Debug.Assert(0 <= n && 1 <= m); if (m == 1) { return(0); } Barrett barrett = new Barrett((uint)m); uint r = 1, y = (uint)InternalMath.SafeMod(x, m); while (0 < n) { if ((n & 1) != 0) { r = barrett.Mul(r, y); } y = barrett.Mul(y, y); n >>= 1; } return(r); }
public static long PowMod(long x, long n, int m) { Contract.Assert(0 <= n && 1 <= m, reason: $"0 <= {nameof(n)} && 1 <= {nameof(m)}"); if (m == 1) { return(0); } Barrett barrett = new Barrett((uint)m); uint r = 1, y = (uint)InternalMath.SafeMod(x, m); while (0 < n) { if ((n & 1) != 0) { r = barrett.Mul(r, y); } y = barrett.Mul(y, y); n >>= 1; } return(r); }
public static long[] ConvolutionLong(ReadOnlySpan <long> a, ReadOnlySpan <long> b) { unchecked { var n = a.Length; var m = b.Length; if (n == 0 || m == 0) { return(Array.Empty <long>()); } const ulong Mod1 = 754974721; // 2^24 const ulong Mod2 = 167772161; // 2^25 const ulong Mod3 = 469762049; // 2^26 const ulong M2M3 = Mod2 * Mod3; const ulong M1M3 = Mod1 * Mod3; const ulong M1M2 = Mod1 * Mod2; // (m1 * m2 * m3) % 2^64 const ulong M1M2M3 = Mod1 * Mod2 * Mod3; const ulong i1 = 190329765; const ulong i2 = 58587104; const ulong i3 = 187290749; Debug.Assert(default(FFTMod1).Mod == Mod1); Debug.Assert(default(FFTMod2).Mod == Mod2); Debug.Assert(default(FFTMod3).Mod == Mod3); Debug.Assert(i1 == (ulong)InternalMath.InvGCD((long)M2M3, (long)Mod1).Item2); Debug.Assert(i2 == (ulong)InternalMath.InvGCD((long)M1M3, (long)Mod2).Item2); Debug.Assert(i3 == (ulong)InternalMath.InvGCD((long)M1M2, (long)Mod3).Item2); var c1 = Convolution <FFTMod1>(a, b); var c2 = Convolution <FFTMod2>(a, b); var c3 = Convolution <FFTMod3>(a, b); var c = new long[n + m - 1]; //ReadOnlySpan<ulong> offset = stackalloc ulong[] { 0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3 }; for (int i = 0; i < c.Length; i++) { ulong x = 0; x += ((ulong)c1[i] * i1) % Mod1 * M2M3; x += ((ulong)c2[i] * i2) % Mod2 * M1M3; x += ((ulong)c3[i] * i3) % Mod3 * M1M2; long diff = c1[i] - InternalMath.SafeMod((long)x, (long)Mod1); if (diff < 0) { diff += (long)Mod1; } // 真値を r, 得られた値を x, M1M2M3 % 2^64 = M', B = 2^63 として、 // r = x, // x - M' + (0 or 2B), // x - 2M' + (0 or 2B or 4B), // x - 3M' + (0 or 2B or 4B or 6B) // のいずれかが成り立つ、らしい // -> see atcoder/convolution.hpp switch (diff % 5) { case 2: x -= M1M2M3; break; case 3: x -= 2 * M1M2M3; break; case 4: x -= 3 * M1M2M3; break; } c[i] = (long)x; } return(c); } }
public void DynamicBorder() { for (int mod = int.MaxValue; mod >= int.MaxValue - 20; mod--) { DynamicModInt <DynamicBorderID> .Mod = mod; var v = new List <long>(); for (int i = 0; i < 10; i++) { v.Add(i); v.Add(mod - i); v.Add(mod / 2 + i); v.Add(mod / 2 - i); } foreach (var a in v) { new DynamicModInt <DynamicBorderID>(a).Pow(3).Value .Should().Be((int)(((a * a) % mod * a) % mod)); foreach (var b in v) { (new DynamicModInt <DynamicBorderID>(a) + b).Value.Should().Be((int)InternalMath.SafeMod(a + b, mod)); (new DynamicModInt <DynamicBorderID>(a) - b).Value.Should().Be((int)InternalMath.SafeMod(a - b, mod)); (new DynamicModInt <DynamicBorderID>(a) * b).Value.Should().Be((int)InternalMath.SafeMod(a * b, mod)); } } } }