Esempio n. 1
0
        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)));
        }
Esempio n. 2
0
 /// <summary>
 /// <paramref name="x"/>y≡1(mod <paramref name="m"/>) なる y のうち、0≤y&lt;<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);
 }
Esempio n. 3
0
 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);
 }
Esempio n. 4
0
 /// <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);
 }
Esempio n. 5
0
        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);
            }
Esempio n. 7
0
 /// <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);
 }
Esempio n. 8
0
 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&lt;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);
        }
Esempio n. 10
0
        /// <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&lt;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);
        }
Esempio n. 11
0
        /// <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);
        }
Esempio n. 12
0
        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);
            }
        }
Esempio n. 14
0
 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));
             }
         }
     }
 }