Beispiel #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)));
        }
Beispiel #2
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);
            }
        /// <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);
        }
Beispiel #5
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);
        }
Beispiel #6
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);
        }
        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);
            }
        }
Beispiel #9
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));
             }
         }
     }
 }