Exemple #1
0
        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)];
                }
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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)];
                }
            }
        }
Exemple #4
0
        public void DivisionNotPrimeTest(int input, int expected)
        {
            var m = StaticModInt <Mod15> .Raw(input);

            var actual = 1 / m;

            Assert.Equal(expected, actual);
        }
Exemple #5
0
    private void ConvolutionMod <T>(int lengthA, int lengthB, ulong seed) where T : struct, IStaticMod
    {
        var rand = new XorShift(seed);
        var a    = new StaticModInt <T> [lengthA];
        var b    = new StaticModInt <T> [lengthB];
        var aRaw = new ulong[lengthA];
        var bRaw = new ulong[lengthB];

        for (int i = 0; i < a.Length; i++)
        {
            aRaw[i] = rand.Next();
            a[i]    = StaticModInt <T> .Raw((int)(aRaw[i] % default(T).Mod));
        }

        for (int i = 0; i < b.Length; i++)
        {
            bRaw[i] = rand.Next();
            b[i]    = StaticModInt <T> .Raw((int)(bRaw[i] % default(T).Mod));
        }

        var expected = new StaticModInt <T> [a.Length + b.Length - 1];

        for (int i = 0; i < a.Length; i++)
        {
            for (int j = 0; j < b.Length; j++)
            {
                expected[i + j] += a[i] * b[j];
            }
        }

        // 各種オーバーロードについてテスト
        var actualModInt     = AtCoder.Math.Convolution(a, b);
        var actualModIntSpan = AtCoder.Math.Convolution((ReadOnlySpan <StaticModInt <T> >)a, b);
        var actualInt        = AtCoder.Math.Convolution <T>(a.Select(ai => ai.Value).ToArray(), b.Select(bi => bi.Value).ToArray());
        var actualUInt       = AtCoder.Math.Convolution <T>(a.Select(ai => (uint)ai.Value).ToArray(), b.Select(bi => (uint)bi.Value).ToArray());
        var actualLong       = AtCoder.Math.Convolution <T>(a.Select(ai => (long)ai.Value).ToArray(), b.Select(bi => (long)bi.Value).ToArray());
        var actualULong      = AtCoder.Math.Convolution <T>(aRaw, bRaw);

        Assert.Equal(expected, actualModInt);
        Assert.Equal(expected, actualModIntSpan.ToArray());
        Assert.Equal(expected.Select(ei => ei.Value), actualInt);
        Assert.Equal(expected.Select(ei => (uint)ei.Value), actualUInt);
        Assert.Equal(expected.Select(ei => (long)ei.Value), actualLong);
        Assert.Equal(expected.Select(ei => (ulong)ei.Value), actualULong);
    }
        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);
        }
Exemple #7
0
        public ModCombination(int max = 1000000)
        {
            if (max >= default(T).Mod)
            {
                ThrowArgumentOutOfRangeException();
            }

            _factorials    = new StaticModInt <T> [max + 1];
            _invFactorials = new StaticModInt <T> [max + 1];

            _factorials[0] = _factorials[1] = StaticModInt <T> .Raw(1);

            _invFactorials[0] = _invFactorials[1] = StaticModInt <T> .Raw(1);

            for (int i = 2; i < _factorials.Length; i++)
            {
                _factorials[i] = _factorials[i - 1] * StaticModInt <T> .Raw(i);
            }

            _invFactorials[^ 1] = _factorials[^ 1].Inverse();
Exemple #8
0
        public void Solve(ConsoleReader cr, ConsoleWriter cw)
        {
            int n = cr;
            int q = cr;

            var seg = new Segtree <(StaticModInt <Mod998244353> a, StaticModInt <Mod998244353> b), SegtreeSolverOp>(
                cr.Repeat(n).Select(cr => (StaticModInt <Mod998244353> .Raw(cr), StaticModInt <Mod998244353> .Raw(cr))));

            for (int i = 0; i < q; i++)
            {
                int t = cr;
                if (t == 0)
                {
                    int p = cr;
                    int c = cr;
                    int d = cr;
                    seg[p] = (StaticModInt <Mod998244353> .Raw(c), StaticModInt <Mod998244353> .Raw(d));
                }
                else
                {
                    int l = cr;
                    int r = cr;
                    int x = cr;
                    var(a, b) = seg[l..r];
        public static void Calculate(Span <StaticModInt <T> > a)
        {
            CheckPow2(a.Length);
            var n = a.Length;
            var h = InternalBit.CeilPow2(n);

            var regLength = Vector <uint> .Count;

#if !NETCOREAPP3_0_OR_GREATER
            var copyTmp = new uint[regLength];
#endif

            // 全要素がmodのVector<uint>を作成(比較および加減算用)
            var modV = new Vector <uint>(default(T).Mod);

            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);
                    var ls     = a.Slice(offset, p);
                    var rs     = a.Slice(offset + p, p);

                    if (p < regLength)
                    {
                        for (int i = 0; i < p; i++)
                        {
                            var l = ls[i];
                            var r = rs[i] * now;
                            ls[i] = l + r;
                            rs[i] = l - r;
                        }
                    }
                    else
                    {
                        foreach (ref var r in rs)
                        {
                            r *= now;
                        }

                        // uintとして再解釈
                        var lu = MemoryMarshal.Cast <StaticModInt <T>, uint>(ls);
                        var ru = MemoryMarshal.Cast <StaticModInt <T>, uint>(rs);

                        for (int i = 0; i < lu.Length; i += regLength)
                        {
                            var luSliced = lu.Slice(i);
                            var ruSliced = ru.Slice(i);
                            var u        = new Vector <uint>(luSliced);
                            var v        = new Vector <uint>(ruSliced);
                            var add      = u + v;
                            var sub      = u - v;

                            var ge = Vector.GreaterThanOrEqual(add, modV);
                            add = Vector.ConditionalSelect(ge, add - modV, add);

                            ge  = Vector.GreaterThanOrEqual(sub, modV);
                            sub = Vector.ConditionalSelect(ge, sub + modV, sub);

#if !NETCOREAPP3_0_OR_GREATER
                            add.CopyTo(copyTmp);
                            copyTmp.CopyTo(luSliced);
                            sub.CopyTo(copyTmp);
                            copyTmp.CopyTo(ruSliced);
#else
                            add.CopyTo(luSliced);
                            sub.CopyTo(ruSliced);
#endif
                        }
                    }

                    now *= sumE[InternalBit.BSF(~(uint)s)];
                }
            }
        }