結果

問題 No.2164 Equal Balls
ユーザー KumaTachiRenKumaTachiRen
提出日時 2023-09-22 16:02:35
言語 C#
(.NET 8.0.203)
結果
TLE  
実行時間 -
コード長 38,169 bytes
コンパイル時間 9,353 ms
コンパイル使用メモリ 166,636 KB
実行使用メモリ 34,820 KB
最終ジャッジ日時 2024-07-08 07:34:18
合計ジャッジ時間 37,230 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 54 ms
28,928 KB
testcase_01 AC 54 ms
25,856 KB
testcase_02 AC 56 ms
25,728 KB
testcase_03 AC 53 ms
25,600 KB
testcase_04 AC 55 ms
25,472 KB
testcase_05 AC 79 ms
28,544 KB
testcase_06 AC 76 ms
28,544 KB
testcase_07 AC 66 ms
26,624 KB
testcase_08 AC 2,063 ms
32,108 KB
testcase_09 AC 863 ms
32,124 KB
testcase_10 AC 522 ms
33,152 KB
testcase_11 AC 3,003 ms
32,540 KB
testcase_12 AC 2,088 ms
32,380 KB
testcase_13 AC 808 ms
31,924 KB
testcase_14 AC 1,924 ms
31,964 KB
testcase_15 AC 2,922 ms
32,496 KB
testcase_16 AC 1,980 ms
32,192 KB
testcase_17 AC 218 ms
34,540 KB
testcase_18 AC 2,427 ms
32,676 KB
testcase_19 TLE -
testcase_20 AC 2,232 ms
32,420 KB
testcase_21 AC 176 ms
32,896 KB
testcase_22 AC 117 ms
30,720 KB
testcase_23 AC 1,515 ms
34,400 KB
testcase_24 TLE -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
testcase_36 -- -
testcase_37 -- -
testcase_38 -- -
testcase_39 -- -
testcase_40 -- -
testcase_41 -- -
testcase_42 -- -
testcase_43 -- -
testcase_44 -- -
testcase_45 -- -
testcase_46 -- -
testcase_47 -- -
testcase_48 -- -
testcase_49 -- -
testcase_50 -- -
testcase_51 -- -
testcase_52 -- -
testcase_53 -- -
権限があれば一括ダウンロードができます
コンパイルメッセージ
  復元対象のプロジェクトを決定しています...
  /home/judge/data/code/main.csproj を復元しました (82 ms)。
MSBuild のバージョン 17.9.6+a4ecab324 (.NET)
  main -> /home/judge/data/code/bin/Release/net8.0/main.dll
  main -> /home/judge/data/code/bin/Release/net8.0/publish/

ソースコード

diff #

using System;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.Intrinsics.X86;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using static Functions;
using static OutputLib;

using ModInt = StaticModInt<Mod998244353>;

static class Program
{
    static public void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver();
        Console.Out.Flush();
    }
}

public class Solver
{
    public Solver()
    {
        Solve();
    }

    void Solve()
    {
        const int l = 300;
        int n = ri, m = ri;
        var a = new int[n];
        var b = new int[n];
        for (int i = 0; i < n; i++) a[i] = ri;
        for (int i = 0; i < n; i++) b[i] = ri;

        var fact = new ModFact<Mod998244353>(10000);

        var f = new ModInt[m * l + 1];
        f[0] = 1;
        for (int k = 0; k < m; k++)
        {
            var c = new ModInt[2 * l + 1];
            Array.Fill(c, 1);
            for (int i = k; i < n; i += m)
                for (int j = -l; j <= l; j++)
                    c[j + l] *= fact.Binom(a[i] + b[i], j + b[i]);
            var g = MathLib.Convolution(f, c);
            for (int i = 0; i <= m * l; i++) f[i] = g[i];
        }
        Write(f[l * m]);
    }

    const long INF = 1L << 60;
    int ri { [MethodImpl(256)] get => (int)sc.Integer(); }
    (int, int) ri2 { [MethodImpl(256)] get => (ri, ri); }
    (int, int, int) ri3 { [MethodImpl(256)] get => (ri, ri, ri); }
    (int, int, int, int) ri4 { [MethodImpl(256)] get => (ri, ri, ri, ri); }
    (int, int, int, int, int) ri5 { [MethodImpl(256)] get => (ri, ri, ri, ri, ri); }
    long rl { [MethodImpl(256)] get => sc.Integer(); }
    (long, long) rl2 { [MethodImpl(256)] get => (rl, rl); }
    (long, long, long) rl3 { [MethodImpl(256)] get => (rl, rl, rl); }
    (long, long, long, long) rl4 { [MethodImpl(256)] get => (rl, rl, rl, rl); }
    (long, long, long, long, long) rl5 { [MethodImpl(256)] get => (rl, rl, rl, rl, rl); }
    uint rui { [MethodImpl(256)] get => (uint)sc.UInteger(); }
    ulong rul { [MethodImpl(256)] get => sc.UInteger(); }
    double rd { [MethodImpl(256)] get => sc.Double(); }
    string rs { [MethodImpl(256)] get => sc.Scan(); }
    string rline { [MethodImpl(256)] get => sc.Line(); }
    public StreamScanner sc = new StreamScanner(Console.OpenStandardInput());
}

public static class Functions
{
    [MethodImpl(256)]
    public static int Popcount(ulong x)
    {
        x = (x & 0x5555555555555555UL) + ((x >> 1) & 0x5555555555555555UL);
        x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL);
        x = (x & 0x0f0f0f0f0f0f0f0fUL) + ((x >> 4) & 0x0f0f0f0f0f0f0f0fUL);
        x = (x & 0x00ff00ff00ff00ffUL) + ((x >> 8) & 0x00ff00ff00ff00ffUL);
        x = (x & 0x0000ffff0000ffffUL) + ((x >> 16) & 0x0000ffff0000ffffUL);
        x = (x & 0x00000000ffffffffUL) + ((x >> 32) & 0x00000000ffffffffUL);
        return (int)x;
    }
    [MethodImpl(256)]
    public static int Popcount(int x)
    {
        x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
        x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
        x = (x & 0x0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f);
        x = (x & 0x00ff00ff) + ((x >> 8) & 0x00ff00ff);
        x = (x & 0x0000ffff) + ((x >> 16) & 0x0000ffff);
        return x;
    }
    [MethodImpl(256)]
    public static int Ctz(long x)
    {
        if (x == 0) return -1;
        return Popcount((ulong)((x & -x) - 1));
    }
    [MethodImpl(256)]
    public static int CeilPow2(int n)
    {
        int x = 0;
        while ((1 << x) < n) x++;
        return x;
    }
    [MethodImpl(256)]
    public static int SafeMod(int x, int m)
    {
        int r = x % m;
        return r < 0 ? r + Math.Abs(m) : r;
    }
    [MethodImpl(256)]
    public static long SafeMod(long x, long m)
    {
        long r = x % m;
        return r < 0 ? r + Math.Abs(m) : r;
    }
    [MethodImpl(256)] public static int Sign(long x) => x == 0 ? 0 : (x < 0 ? -1 : 1);
    [MethodImpl(256)] public static int Sign(double x) => x == 0 ? 0 : (x < 0 ? -1 : 1);
    [MethodImpl(256)] public static int DigitSum(long n, int d = 10) { long s = 0; while (n > 0) { s += n % d; n /= d; } return (int)s; }
    [MethodImpl(256)] public static long Floor(long a, long b) => a >= 0 ? a / b : (a + 1) / b - 1;
    [MethodImpl(256)] public static long Ceil(long a, long b) => a > 0 ? (a - 1) / b + 1 : a / b;
    [MethodImpl(256)] public static int Gcd(int a, int b) => b == 0 ? a : Gcd(b, a % b);
    [MethodImpl(256)] public static long Gcd(long a, long b) => b == 0 ? a : Gcd(b, a % b);
    [MethodImpl(256)] public static (long x, long y, long g) ExtGcd(long a, long b) { if (b == 0) return (Sign(a), 0, Math.Abs(a)); long c = SafeMod(a, b); var (x2, y2, g) = ExtGcd(b, c); long x = SafeMod(y2, b); long y = (g - a * x) / b; return (x, y, g); }
    [MethodImpl(256)] public static void Swap(ref int x, ref int y) { x ^= y; y ^= x; x ^= y; }
    [MethodImpl(256)] public static void Swap(ref long x, ref long y) { x ^= y; y ^= x; x ^= y; }
    [MethodImpl(256)] public static void Swap<T>(ref T x, ref T y) { T t = y; y = x; x = t; }
    [MethodImpl(256)] public static T Clamp<T>(T x, T l, T r) where T : IComparable<T> => x.CompareTo(l) <= 0 ? l : (x.CompareTo(r) <= 0 ? x : r);
    [MethodImpl(256)] public static T Clamp<T>(ref T x, T l, T r) where T : IComparable<T> => x = x.CompareTo(l) <= 0 ? l : (x.CompareTo(r) <= 0 ? x : r);
    [MethodImpl(256)] public static void Chmin<T>(ref T x, T y) where T : IComparable<T> { if (x.CompareTo(y) > 0) x = y; }
    [MethodImpl(256)] public static void Chmax<T>(ref T x, T y) where T : IComparable<T> { if (x.CompareTo(y) < 0) x = y; }
    [MethodImpl(256)] public static int LowerBound(long[] arr, long val, int l = -1, int r = -1) => LowerBound(arr.AsSpan(), t => Sign(t - val), l, r);
    [MethodImpl(256)] public static int LowerBound(int[] arr, int val, int l = -1, int r = -1) => LowerBound(arr.AsSpan(), t => t - val, l, r);
    [MethodImpl(256)] public static int LowerBound<T>(T[] arr, T val, int l = -1, int r = -1) where T : IComparable<T> => LowerBound(arr.AsSpan(), t => t.CompareTo(val), l, r);
    [MethodImpl(256)] public static int LowerBound<T>(T[] arr, Func<T, int> comp, int l = -1, int r = -1) => LowerBound(arr.AsSpan(), comp, l, r);
    [MethodImpl(256)] public static int LowerBound<T>(Span<T> data, Func<T, int> comp, int l = -1, int r = -1) { if (data.Length == 0) return -1; if (l == -1) l = 0; if (r == -1) r = data.Length; while (l < r) { int x = (l + r) / 2; if (comp(data[x]) < 0) l = x + 1; else r = x; } return l; }
    [MethodImpl(256)] public static string ToBase2(long v, int digit = -1) { if (digit == -1) { digit = 0; while ((v >> digit) > 0) digit++; } var c = new string[digit]; for (int i = 0; i < digit; i++) c[digit - 1 - i] = ((v >> i) & 1) == 0 ? "0" : "1"; return string.Join("", c); }
    [MethodImpl(256)] public static string ToBaseN(long v, int n, int digit = -1) { if (digit == -1) { digit = 0; long pow = 1; while (v >= pow) { digit++; pow *= n; } } var c = new int[digit]; for (int i = 0; i < digit; i++, v /= n) c[digit - 1 - i] = (int)(v % n); return string.Join("", c); }
}

public class StreamScanner
{
    public StreamScanner(Stream stream) { str = stream; }
    private readonly Stream str;
    private readonly byte[] buf = new byte[1024];
    private int len, ptr;
    public bool isEof = false;
    public bool IsEndOfStream { get { return isEof; } }
    [MethodImpl(256)] private byte read() { if (isEof) throw new EndOfStreamException(); if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } } return buf[ptr++]; }
    [MethodImpl(256)] public char Char() { byte b = 0; do b = read(); while (b < 33 || 126 < b); return (char)b; }
    [MethodImpl(256)] public string Line() { var sb = new StringBuilder(); for (var b = Char(); b != 10 && !isEof; b = (char)read()) sb.Append(b); return sb.ToString(); }
    [MethodImpl(256)] public string Scan() { var sb = new StringBuilder(); for (var b = Char(); b >= 33 && b <= 126; b = (char)read()) sb.Append(b); return sb.ToString(); }
    [MethodImpl(256)] public long Integer() { long ret = 0; byte b = 0; var ng = false; do b = read(); while (b != '-' && (b < '0' || '9' < b)); if (b == '-') { ng = true; b = read(); } for (; true; b = read()) { if (b < '0' || '9' < b) return ng ? -ret : ret; else ret = ret * 10 + b - '0'; } }
    [MethodImpl(256)] public ulong UInteger() { ulong ret = 0; byte b = 0; do b = read(); while (b < '0' || '9' < b); for (; true; b = read()) { if (b < '0' || '9' < b) return ret; else ret = ret * 10 + b - '0'; } }
    [MethodImpl(256)] public double Double() => double.Parse(Scan());
}

public static class OutputLib
{
    [MethodImpl(256)] public static void WriteJoin<T>(string s, IEnumerable<T> t) => Console.WriteLine(string.Join(s, t));
    [MethodImpl(256)] public static void WriteMat<T>(T[,] a) { int sz1 = a.GetLength(0); int sz2 = a.GetLength(1); for (int i = 0; i < sz1; i++) { var b = new T[sz2]; for (int j = 0; j < sz2; j++) b[j] = a[i, j]; WriteJoin(" ", b); } }
    [MethodImpl(256)] public static void WriteMat<T>(T[][] a) { for (int i = 0; i < a.Length; i++) WriteJoin(" ", a[i]); }
    [MethodImpl(256)] public static void Write(object t) => Console.WriteLine(t.ToString());
    [MethodImpl(256)] public static void Write(string str) => Console.WriteLine(str);
    [MethodImpl(256)] public static void Write(string str, object arg1) => Console.WriteLine(str, arg1);
    [MethodImpl(256)] public static void Write(string str, object arg1, object arg2) => Console.WriteLine(str, arg1, arg2);
    [MethodImpl(256)] public static void Write(string str, object arg1, object arg2, object arg3) => Console.WriteLine(str, arg1, arg2, arg3);
    [MethodImpl(256)] public static void Write(string str, params object[] arg) => Console.WriteLine(str, arg);
    [MethodImpl(256)] public static void WriteFlush(object t) { Console.WriteLine(t.ToString()); Console.Out.Flush(); }
    [MethodImpl(256)] public static void WriteError(object t) => Console.Error.WriteLine(t.ToString());
    [MethodImpl(256)] public static void Flush() => Console.Out.Flush();
    [MethodImpl(256)] public static void YN(bool t) => Console.WriteLine(t ? "YES" : "NO");
    [MethodImpl(256)] public static void Yn(bool t) => Console.WriteLine(t ? "Yes" : "No");
    [MethodImpl(256)] public static void yn(bool t) => Console.WriteLine(t ? "yes" : "no");
}

public interface IStaticMod
{
    uint Mod { get; }
    bool IsPrime { get; }
}
public readonly struct Mod1000000007 : IStaticMod
{
    public uint Mod => 1000000007;
    public bool IsPrime => true;
}
public readonly struct Mod998244353 : IStaticMod
{
    public uint Mod => 998244353;
    public bool IsPrime => true;
}
public readonly struct StaticModInt<T> : IEquatable<StaticModInt<T>>, IFormattable where T : struct, IStaticMod
{
    internal readonly uint _v;
    private static readonly T op = default;
    public int Value => (int)_v;
    public static int Mod => (int)op.Mod;
    public static StaticModInt<T> Zero => default;
    public static StaticModInt<T> One => new StaticModInt<T>(1u);
    [MethodImpl(256)]
    public static StaticModInt<T> Raw(int v)
    {
        var u = unchecked((uint)v);
        return new StaticModInt<T>(u);
    }
    [MethodImpl(256)]
    public StaticModInt(long v) : this(Round(v)) { }
    [MethodImpl(256)]
    public StaticModInt(ulong v) : this((uint)(v % op.Mod)) { }
    [MethodImpl(256)]
    private StaticModInt(uint v) => _v = v;
    [MethodImpl(256)]
    private static uint Round(long v)
    {
        var x = v % op.Mod;
        if (x < 0) x += op.Mod;
        return (uint)x;
    }
    [MethodImpl(256)]
    public static StaticModInt<T> operator ++(StaticModInt<T> v)
    {
        var x = v._v + 1;
        if (x == op.Mod) x = 0;
        return new StaticModInt<T>(x);
    }
    [MethodImpl(256)]
    public static StaticModInt<T> operator --(StaticModInt<T> v)
    {
        var x = v._v;
        if (x == 0) x = op.Mod;
        return new StaticModInt<T>(x - 1);
    }
    [MethodImpl(256)]
    public static StaticModInt<T> operator +(StaticModInt<T> lhs, StaticModInt<T> rhs)
    {
        var v = lhs._v + rhs._v;
        if (v >= op.Mod) v -= op.Mod;
        return new StaticModInt<T>(v);
    }
    [MethodImpl(256)]
    public static StaticModInt<T> operator -(StaticModInt<T> lhs, StaticModInt<T> rhs)
    {
        unchecked
        {
            var v = lhs._v - rhs._v;
            if (v >= op.Mod) v += op.Mod;
            return new StaticModInt<T>(v);
        }
    }
    [MethodImpl(256)]
    public static StaticModInt<T> operator *(StaticModInt<T> lhs, StaticModInt<T> rhs) => new StaticModInt<T>((uint)((ulong)lhs._v * rhs._v % op.Mod));
    [MethodImpl(256)]
    public static StaticModInt<T> operator /(StaticModInt<T> lhs, StaticModInt<T> rhs) => lhs * rhs.Inv();
    [MethodImpl(256)]
    public static StaticModInt<T> operator +(StaticModInt<T> v) => v;
    [MethodImpl(256)]
    public static StaticModInt<T> operator -(StaticModInt<T> v) => new StaticModInt<T>(v._v == 0 ? 0 : op.Mod - v._v);
    [MethodImpl(256)]
    public static bool operator ==(StaticModInt<T> lhs, StaticModInt<T> rhs) => lhs._v == rhs._v;
    [MethodImpl(256)]
    public static bool operator !=(StaticModInt<T> lhs, StaticModInt<T> rhs) => lhs._v != rhs._v;
    [MethodImpl(256)]
    public static implicit operator StaticModInt<T>(int v) => new StaticModInt<T>(v);
    [MethodImpl(256)]
    public static implicit operator StaticModInt<T>(uint v) => new StaticModInt<T>((long)v);
    [MethodImpl(256)]
    public static implicit operator StaticModInt<T>(long v) => new StaticModInt<T>(v);
    [MethodImpl(256)]
    public static implicit operator StaticModInt<T>(ulong v) => new StaticModInt<T>(v);
    [MethodImpl(256)]
    public static implicit operator long(StaticModInt<T> v) => v._v;
    [MethodImpl(256)]
    public static implicit operator ulong(StaticModInt<T> v) => v._v;
    [MethodImpl(256)]
    public StaticModInt<T> Pow(long n)
    {
        var x = this;
        var r = new StaticModInt<T>(1U);
        while (n > 0)
        {
            if ((n & 1) > 0) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    [MethodImpl(256)]
    public StaticModInt<T> Inv()
    {
        var (x, y, g) = ExtGcd(_v, op.Mod);
        return new StaticModInt<T>(x);
    }
    [MethodImpl(256)]
    static (long x, long y, long g) ExtGcd(long a, long b)
    {
        if (b == 0) return a >= 0 ? (1, 0, a) : (-1, 0, -a);
        long c = SafeMod(a, b);
        var (x2, y2, g) = ExtGcd(b, c);
        long x = SafeMod(y2, b);
        long y = (g - a * x) / b;
        return (x, y, g);
    }
    [MethodImpl(256)]
    static long SafeMod(long x, long m)
    {
        long r = x % m;
        if (r < 0) r += m;
        return r;
    }
    [MethodImpl(256)]
    public override string ToString() => _v.ToString();
    [MethodImpl(256)]
    public string ToString(string format, IFormatProvider formatProvider) => _v.ToString(format, formatProvider);
    [MethodImpl(256)]
    public override bool Equals(object obj) => obj is StaticModInt<T> m && Equals(m);
    [MethodImpl(256)]
    public bool Equals(StaticModInt<T> other) => _v == other._v;
    [MethodImpl(256)]
    public override int GetHashCode() => _v.GetHashCode();
}

public static partial class MathLib
{
    [MethodImpl(256)]
    public static long[] Convolution<TMod>(ReadOnlySpan<long> a, ReadOnlySpan<long> b) where TMod : struct, IStaticMod
    {
        var u = new StaticModInt<TMod>[a.Length];
        for (int i = 0; i < a.Length; i++) u[i] = a[i];
        var v = new StaticModInt<TMod>[b.Length];
        for (int i = 0; i < b.Length; i++) v[i] = b[i];
        u = Convolution(u, v);
        var r = new long[u.Length];
        for (int i = 0; i < u.Length; i++) r[i] = u[i];
        return r;
    }

    [MethodImpl(256)]
    public static StaticModInt<TMod>[] Convolution<TMod>(ReadOnlySpan<StaticModInt<TMod>> a, ReadOnlySpan<StaticModInt<TMod>> b) where TMod : struct, IStaticMod
    {
        var n = a.Length;
        var m = b.Length;
        if (n == 0 || m == 0)
            return Array.Empty<StaticModInt<TMod>>();
        if (Math.Min(n, m) <= 30)
            return ConvolutionNaive(a, b);
        return ConvolutionFFT(a, b);
    }

    [MethodImpl(256)]
    public static StaticModInt<TMod>[] Convolution<TMod>(StaticModInt<TMod>[] a, StaticModInt<TMod>[] b) where TMod : struct, IStaticMod
        => Convolution((ReadOnlySpan<StaticModInt<TMod>>)a, b);

    [MethodImpl(256)]
    private static StaticModInt<TMod>[] ConvolutionFFT<TMod>(ReadOnlySpan<StaticModInt<TMod>> a, ReadOnlySpan<StaticModInt<TMod>> b) where TMod : struct, IStaticMod
    {
        int n = a.Length, m = b.Length;
        int z = 1 << InternalBit.CeilPow2(n + m - 1);
        var a2 = new StaticModInt<TMod>[z];
        var b2 = new StaticModInt<TMod>[z];
        a.CopyTo(a2);
        b.CopyTo(b2);

        var result = ConvolutionFFTInner(a2, b2);
        Array.Resize(ref result, n + m - 1);
        var iz = new StaticModInt<TMod>(z).Inv();
        for (int i = 0; i < result.Length; i++)
            result[i] *= iz;

        return result;
    }

    [MethodImpl(256)]
    private static StaticModInt<TMod>[] ConvolutionFFTInner<TMod>(StaticModInt<TMod>[] a, StaticModInt<TMod>[] b) where TMod : struct, IStaticMod
    {
        Butterfly<TMod>.Calculate(a);
        Butterfly<TMod>.Calculate(b);
        for (int i = 0; i < a.Length; i++)
            a[i] *= b[i];
        Butterfly<TMod>.CalculateInv(a);
        return a;
    }
    [MethodImpl(256)]
    private static StaticModInt<TMod>[] ConvolutionNaive<TMod>(ReadOnlySpan<StaticModInt<TMod>> a, ReadOnlySpan<StaticModInt<TMod>> b) where TMod : struct, IStaticMod
    {
        if (a.Length < b.Length)
        {
#pragma warning disable IDE0180
            var temp = a;
            a = b;
            b = temp;
#pragma warning restore IDE0180
        }

        var ans = new StaticModInt<TMod>[a.Length + b.Length - 1];
        for (int i = 0; i < a.Length; i++)
        {
            for (int j = 0; j < b.Length; j++)
            {
                ans[i + j] += a[i] * b[j];
            }
        }

        return ans;
    }

    [MethodImpl(256)]
    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;
            const ulong Mod2 = 167772161;
            const ulong Mod3 = 469762049;
            const ulong M2M3 = Mod2 * Mod3;
            const ulong M1M3 = Mod1 * Mod3;
            const ulong M1M2 = Mod1 * Mod2;

            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];

            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;

                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;
        }
    }

    [MethodImpl(256)]
    public static StaticModInt<Mod>[] ConvolutionIntMod<Mod>(ReadOnlySpan<StaticModInt<Mod>> a, ReadOnlySpan<StaticModInt<Mod>> b) where Mod : struct, IStaticMod
    {
        var n = a.Length;
        var m = b.Length;

        if (n == 0 || m == 0) return Array.Empty<StaticModInt<Mod>>();

        const long Mod1 = 754974721;
        const long Mod2 = 167772161;
        const long Mod3 = 469762049;
        const long M1invM2 = 95869806;
        const long M12invM3 = 187290749;
        int mod = StaticModInt<Mod>.Mod;
        long M12mod = Mod1 * Mod2 % mod;

        var u = new long[n];
        for (int i = 0; i < n; i++) u[i] = a[i];
        var v = new long[m];
        for (int i = 0; i < m; i++) v[i] = b[i];
        var c1 = Convolution<FFTMod1>(u, v);
        var c2 = Convolution<FFTMod2>(u, v);
        var c3 = Convolution<FFTMod3>(u, v);

        var c = new StaticModInt<Mod>[n + m - 1];
        for (int i = 0; i < c.Length; i++)
        {
            long v1 = (c2[i] - c1[i]) * M1invM2 % Mod2;
            if (v1 < 0) v1 += Mod2;
            long v2 = (c3[i] - (c1[i] + Mod1 * v1) % Mod3) * M12invM3 % Mod3;
            if (v2 < 0) v2 += Mod3;
            long v3 = (c1[i] + Mod1 * v1 + M12mod * v2) % mod;
            if (v3 < 0) v3 += mod;
            c[i] = v3;
        }
        return c;
    }

    private readonly struct FFTMod1 : IStaticMod
    {
        public uint Mod => 754974721;
        public bool IsPrime => true;
    }

    private readonly struct FFTMod2 : IStaticMod
    {
        public uint Mod => 167772161;
        public bool IsPrime => true;
    }

    private readonly struct FFTMod3 : IStaticMod
    {
        public uint Mod => 469762049;
        public bool IsPrime => true;
    }
}

class ModFact<TMod> where TMod : struct, IStaticMod
{
    StaticModInt<TMod>[] fact;
    StaticModInt<TMod>[] factinv;
    StaticModInt<TMod>[] inv;
    public ModFact(long n)
    {
        fact = new StaticModInt<TMod>[n + 1];
        factinv = new StaticModInt<TMod>[n + 1];
        inv = new StaticModInt<TMod>[n + 1];
        fact[0] = 1;
        for (long i = 0; i < n; i++) fact[i + 1] = fact[i] * (i + 1);
        factinv[n] = fact[n].Inv();
        for (long i = n; i > 0; i--) factinv[i - 1] = factinv[i] * i;
        for (long i = 1; i <= n; i++) inv[i] = fact[i - 1] * factinv[i];
    }
    [MethodImpl(256)]
    public StaticModInt<TMod> Fact(long n) => fact[n];
    [MethodImpl(256)]
    public StaticModInt<TMod> FactInv(long n) => factinv[n];
    [MethodImpl(256)]
    public StaticModInt<TMod> Inv(long n)
    {
        if (n == 0) throw new DivideByZeroException();
        return inv[n];
    }
    [MethodImpl(256)]
    public StaticModInt<TMod> Binom(long n, long k)
    {
        if (n < 0) return 0;
        if (n == 0) return k == 0 ? 1 : 0;
        return 0 <= k && k <= n ? fact[n] * factinv[k] * factinv[n - k] : 0;
    }
}

public static class InternalBit
{

    [MethodImpl(256)]
    public static uint ExtractLowestSetBit(int n)
    {
#if NETCOREAPP3_0_OR_GREATER
        if (Bmi1.IsSupported)
        {
            return Bmi1.ExtractLowestSetBit((uint)n);
        }
#endif
        return (uint)(n & -n);
    }

    [MethodImpl(256)]
    public static int Bsf(uint n)
    {
#if EMBEDDING
            Contract.Assert(n > 0, reason: $"{nameof(n)} must positive");
#endif
        return BitOperations.TrailingZeroCount(n);
    }

    [MethodImpl(256)]
    public static int CeilPow2(int n)
    {
        var un = (uint)n;
        if (un <= 1) return 0;
        return BitOperations.Log2(un - 1) + 1;
    }
}

public static class InternalMath
{
    private static readonly Dictionary<uint, int> primitiveRootsCache = new Dictionary<uint, int>()
    {
        { 2, 1 },
        { 167772161, 3 },
        { 469762049, 3 },
        { 754974721, 11 },
        { 998244353, 3 }
    };

    [MethodImpl(256)]
    public static int PrimitiveRoot<TMod>() where TMod : struct, IStaticMod
    {
        uint m = default(TMod).Mod;
        Contract.Assert(m >= 2, $"{nameof(m)} must be greater or equal 2");
        Contract.Assert(default(TMod).IsPrime, $"{nameof(m)} must be prime number");

#if NET7_0_OR_GREATER
        ref var result = ref System.Runtime.InteropServices.CollectionsMarshal.GetValueRefOrAddDefault(primitiveRootsCache, m, out var exists);
        if (!exists)
        {
            result = PrimitiveRootCalculate<TMod>();
        }
        return result;
#else
        if (primitiveRootsCache.TryGetValue(m, out var p))
        {
            return p;
        }

        return primitiveRootsCache[m] = PrimitiveRootCalculate<TMod>();
#endif
    }
    static int PrimitiveRootCalculate<TMod>() where TMod : struct, IStaticMod
    {
        var m = default(TMod).Mod;
        Span<uint> divs = stackalloc uint[20];
        divs[0] = 2;
        int cnt = 1;
        var x = m - 1;
        x >>= BitOperations.TrailingZeroCount(x);

        for (uint i = 3; (long)i * i <= x; i += 2)
        {
            if (x % i == 0)
            {
                divs[cnt++] = i;
                do
                {
                    x /= i;
                } while (x % i == 0);
            }
        }

        if (x > 1)
        {
            divs[cnt++] = x;
        }
        divs = divs.Slice(0, cnt);

        for (int g = 2; ; g++)
        {
            foreach (var d in divs)
                if (new StaticModInt<TMod>(g).Pow((m - 1) / d).Value == 1)
                    goto NEXT;
            return g;
        NEXT:;
        }
    }

    [MethodImpl(256)]
    public static (long, long) InvGcd(long a, long b)
    {
        a = SafeMod(a, b);
        if (a == 0) return (b, 0);

        long s = b, t = a;
        long m0 = 0, m1 = 1;

        long u;
        while (true)
        {
            if (t == 0)
            {
                if (m0 < 0) m0 += b / s;
                return (s, m0);
            }
            u = s / t;
            s -= t * u;
            m0 -= m1 * u;

            if (s == 0)
            {
                if (m1 < 0) m1 += b / t;
                return (t, m1);
            }
            u = t / s;
            t -= s * u;
            m1 -= m0 * u;
        }
    }

    [MethodImpl(256)]
    public static long SafeMod(long x, long m)
    {
        x %= m;
        if (x < 0) x += m;
        return x;
    }

    [MethodImpl(256)]
    public static bool IsPrime(int n)
    {
        if (n <= 1) return false;
        if (n == 2 || n == 7 || n == 61) return true;
        if (n % 2 == 0) return false;
        long d = n - 1;
        while (d % 2 == 0) d /= 2;
        ReadOnlySpan<byte> bases = stackalloc byte[3] { 2, 7, 61 };
        foreach (long a in bases)
        {
            long t = d;
            long y = PowMod(a, t, n);
            while (t != n - 1 && y != 1 && y != n - 1)
            {
                y = y * y % n;
                t <<= 1;
            }
            if (y != n - 1 && t % 2 == 0)
            {
                return false;
            }
        }
        return true;
    }

    [MethodImpl(256)]
    public static uint PowMod(long x, long n, int m)
    {
        Contract.Assert(0 <= n && 1 <= m, $"0 <= {nameof(n)} && 1 <= {nameof(m)}");
        if (m == 1) return 0;
        return new Barrett((uint)m).Pow(x, n);
    }

    [MethodImpl(256)]
    public static uint PowMod(long x, long n, uint m)
    {
        Contract.Assert(0 <= n && 1 <= m, $"0 <= {nameof(n)} && 1 <= {nameof(m)}");
        if (m == 1) return 0;
        return new Barrett(m).Pow(x, n);
    }

    [MethodImpl(256)]
    public static ulong FloorSumUnsigned(ulong n, ulong m, ulong a, ulong b)
    {
        ulong ans = 0;
        while (true)
        {
            if (a >= m)
            {
                ans += (n - 1) * n / 2 * (a / m);
                a %= m;
            }
            if (b >= m)
            {
                ans += n * (b / m);
                b %= m;
            }

            ulong yMax = a * n + b;
            if (yMax < m) return ans;
            (n, m, a, b) = (yMax / m, a, m, yMax % m);
        }
    }

    [MethodImpl(256)]
    public static ulong Mul128Bit(ulong a, ulong b)
    {
#if NETCOREAPP3_1_OR_GREATER
        if (Bmi2.X64.IsSupported)
            return Bmi2.X64.MultiplyNoFlags(a, b);
#endif
        return Mul128BitLogic(a, b);
    }

    [MethodImpl(256)]
    internal static ulong Mul128BitLogic(ulong a, ulong b)
    {

        var au = a >> 32;
        var ad = a & 0xFFFFFFFF;
        var bu = b >> 32;
        var bd = b & 0xFFFFFFFF;

        var l = ad * bd;
        var m1 = au * bd;
        var m2 = ad * bu;
        var h = au * bu;

        var lu = l >> 32;
        var m1d = m1 & 0xFFFFFFFF;
        var m2d = m2 & 0xFFFFFFFF;
        var c = m1d + m2d + lu;

        return h + (m1 >> 32) + (m2 >> 32) + (c >> 32);
    }
}

public static class Butterfly<T> where T : struct, IStaticMod
{

    [EditorBrowsable(EditorBrowsableState.Never)]
    public static readonly StaticModInt<T>[] sumE = CalcurateSumE();

    [EditorBrowsable(EditorBrowsableState.Never)]
    public static readonly StaticModInt<T>[] sumIE = CalcurateSumIE();

    [MethodImpl(256)]
    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

        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);

            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;
                    }

                    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)];
            }
        }
    }
    [MethodImpl(256)]
    public static void CalculateInv(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

        var modV = new Vector<uint>(default(T).Mod);

        for (int ph = h; ph >= 1; ph--)
        {

            int w = 1 << (ph - 1);

            int p = 1 << (h - ph);

            var iNow = StaticModInt<T>.Raw(1);

            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];
                        ls[i] = l + r;
                        rs[i] = StaticModInt<T>.Raw(
                            (int)((ulong)(default(T).Mod + l.Value - r.Value) * (ulong)iNow.Value % default(T).Mod));
                    }
                }
                else
                {

                    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);

                        sub += modV;

#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
                    }

                    foreach (ref var r in rs)
                    {
                        r *= iNow;
                    }
                }
                iNow *= sumIE[InternalBit.Bsf(~(uint)s)];
            }
        }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public static StaticModInt<T>[] CalcurateSumE()
    {
        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 sumE = new StaticModInt<T>[30];

        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--)
        {

            es[i] = e;
            ies[i] = ie;
            e *= e;
            ie *= ie;
        }

        var now = StaticModInt<T>.Raw(1);
        for (int i = 0; i <= cnt2 - 2; i++)
        {
            sumE[i] = es[i] * now;
            now *= ies[i];
        }

        return sumE;
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public 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];

        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--)
        {

            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;
    }

    [Conditional("ATCODER_CONTRACT")]
    private static void CheckPow2(int n)
    {
        if (BitOperations.PopCount((uint)n) != 1)
        {
            throw new ArgumentException("配列長は2のべき乗でなければなりません。");
        }
    }
}

public class Barrett
{
    public readonly uint Mod;
    public readonly ulong IM;
    public Barrett(uint m)
    {
        Mod = m;
        IM = unchecked((ulong)-1) / m + 1;
    }

    [MethodImpl(256)]
    public uint Mul(uint a, uint b) => Reduce((ulong)a * b);

    [MethodImpl(256)]
    public uint Reduce(ulong z)
    {
        var x = InternalMath.Mul128Bit(z, IM);
        var v = unchecked((uint)(z - x * Mod));
        if (Mod <= v) v += Mod;
        return v;
    }

    [MethodImpl(256)]
    public uint Pow(long x, long n)
    {
        Contract.Assert(0 <= n, $"{nameof(n)} must be positive.");
        if (Mod == 1) return 0;
        uint r = 1, y = (uint)InternalMath.SafeMod(x, Mod);
        while (n > 0)
        {
            if ((n & 1) != 0) r = Mul(r, y);
            y = Mul(y, y);
            n >>= 1;
        }
        return r;
    }
}
0