結果
| 問題 | No.3540 Arise |
| コンテスト | |
| ユーザー |
nauclhlt
|
| 提出日時 | 2026-03-07 01:15:20 |
| 言語 | C# (.NET 10.0.201) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 33,566 bytes |
| 記録 | |
| コンパイル時間 | 9,238 ms |
| コンパイル使用メモリ | 174,592 KB |
| 実行使用メモリ | 215,992 KB |
| 最終ジャッジ日時 | 2026-05-08 20:54:21 |
| 合計ジャッジ時間 | 24,238 ms |
|
ジャッジサーバーID (参考情報) |
judge2_0 / judge3_1 |
(要ログイン)
| サブタスク | 配点 | 結果 |
|---|---|---|
| サブタスク1 | 30 % | RE * 19 |
| サブタスク2 | 70 % | AC * 6 RE * 16 |
| 合計 | 3.5 * 0% = 0 点 |
コンパイルメッセージ
復元対象のプロジェクトを決定しています... /home/judge/data/code/main.csproj を復元しました (120 ミリ秒)。 main -> /home/judge/data/code/bin/Release/net10.0/main.dll main -> /home/judge/data/code/bin/Release/net10.0/publish/
ソースコード
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static Tmpl;
using System.Globalization;
using System.Diagnostics;
StreamWriter writer = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
Console.SetOut(writer);
Solver.Solve();
Console.Out.Flush();
public static class Solver
{
private static readonly AtCoderIO cin = new AtCoderIO();
public static unsafe void Solve()
{
int N = cin.Int();
ModInt<Mod998244353>[] A = cin.ModIntArray<Mod998244353>(N);
ModInt<Mod998244353>[] invA = new ModInt<Mod998244353>[N];
for (int i = 0; i < N; i++)
{
invA[i] = A[i].Inv();
}
Ensure(1 <= N && N <= 1500);
Array.Sort(A);
for (int i = 0; i < N; i++)
{
if (i < N - 1)
{
Ensure(A[i] != A[i + 1]);
}
}
ModInt<Mod998244353> ans = 0L;
for (int i = 0; i < N; i++)
{
ans += (A[i] + 1) / (ModInt<Mod998244353>)2L;
}
if ((long)A[0] <= N + 2)
{
print(SolveNaive(N, A, invA));
return;
}
ModInt<Mod998244353>[] F = new ModInt<Mod998244353>[N + 3];
for (int x = 1; x <= N + 2; x++)
{
ModInt<Mod998244353> left = 1L;
ModInt<Mod998244353> right = 1L;
for (int i = 1; i < N; i++)
{
right *= (A[i] - x) * invA[i];
}
for (int k = 0; k < N; k++)
{
F[x] += (A[k] - x) * left * right * invA[k];
left *= (A[k] - x + 1) * invA[k];
if (k < N - 1)
{
right /= (ModInt<Mod998244353>)(A[k + 1] - x) * invA[k + 1];
}
}
}
ModInt<Mod998244353>[] G = new ModInt<Mod998244353>[N + 3];
G[1] = F[1];
for (int j = 2; j <= N + 2; j++)
{
G[j] = G[j - 1] + F[j];
}
ModCache<Mod998244353> cache = new(N + 100);
ModInt<Mod998244353>[] prefix = new ModInt<Mod998244353>[N + 3];
ModInt<Mod998244353>[] suffix = new ModInt<Mod998244353>[N + 3];
prefix[0] = 1L;
suffix[N + 2] = 1L;
for (int i = 1; i <= N + 2; i++)
{
prefix[i] = prefix[i - 1] * (A[0] - i);
}
for (int i = N + 1; i >= 0; i--)
{
suffix[i] = suffix[i + 1] * (A[0] - i - 1);
}
for (int i = 1; i <= N + 2; i++)
{
long sign = (i - N + 2) % 2 == 0 ? 1 : -1;
ans += G[i] * (prefix[i - 1] * suffix[i]) * (cache.InverseFactorial(i - 1) * sign * cache.InverseFactorial(N + 2 - i));
}
print(ans);
}
private static ModInt<Mod998244353> SolveNaive(int N, ModInt<Mod998244353>[] A, ModInt<Mod998244353>[] invA)
{
ModInt<Mod998244353> ans = 0L;
for (int i = 0; i < N; i++)
{
ans += (A[i] + 1) / (ModInt<Mod998244353>)2L;
}
for (int m = 1; m <= A[0]; m++)
{
ModInt<Mod998244353> left = 1L;
ModInt<Mod998244353> right = 1L;
for (int i = 1; i < N; i++)
{
right *= (A[i] - m) * invA[i];
}
for (int k = 0; k < N; k++)
{
ans += (A[k] - m) * left * right * invA[k];
left *= (A[k] - m + 1) * invA[k];
if (k < N - 1)
{
right *= A[k + 1] / (A[k + 1] - m);
}
}
}
return ans;
}
private static void Ensure(bool condition)
{
if (!condition)
{
throw new InvalidOperationException();
}
}
}
/// <summary>
/// ModIntの階乗、階乗の逆元、逆元を前計算。
/// </summary>
public sealed class ModCache<T> where T : struct, IMod
{
private ModInt<T>[] _factorial;
private ModInt<T>[] _inverseFactorial;
private ModInt<T>[] _inverse;
// 階乗(&階乗逆元)と逆元を前計算する.
// O(max)
public ModCache(long max)
{
_factorial = new ModInt<T>[max + 1];
_inverseFactorial = new ModInt<T>[max + 1];
_factorial[0] = 1;
_inverseFactorial[0] = ModInt<T>.One;
_inverse = new ModInt<T>[max + 1];
_inverse[1] = ModInt<T>.CreateFast(1);
for (long p = 1; p <= max; p++)
{
_factorial[p] = _factorial[p - 1] * p;
if (p > 1)
{
_inverse[p] = -(ModInt<T>.Mod / p) * _inverse[ModInt<T>.Mod % p];
}
_inverseFactorial[p] = _inverseFactorial[p - 1] * _inverse[p];
}
}
/// <summary>
/// binom(n, r)を返す。r<0またはr>nのとき0を返す。計算量: O(1)
/// </summary>
/// <param name="n"></param>
/// <param name="r"></param>
/// <returns></returns>
public ModInt<T> Combination(long n, long r)
{
if (r < 0 || r > n) return 0;
return _factorial[n] * (_inverseFactorial[n - r] * _inverseFactorial[r]);
}
/// <summary>
/// nPrを返す。r<0またはr>nのとき0を返す。計算量: O(1)
/// </summary>
/// <param name="n"></param>
/// <param name="r"></param>
/// <returns></returns>
public ModInt<T> Permutation(long n, long r)
{
if (r < 0 || r > n) return 1;
return _factorial[n] * _inverseFactorial[n - r];
}
/// <summary>
/// n!の値を返す。計算量: O(1)
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public ModInt<T> Factorial(long n)
{
Debug.Assert(0 <= n && n < _factorial.Length);
return _factorial[n];
}
/// <summary>
/// n!の乗法逆元(n!)^{-1}の値を返す。計算量: O(1)
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public ModInt<T> InverseFactorial(int n)
{
Debug.Assert(0 <= n && n < _inverseFactorial.Length);
return _inverseFactorial[n];
}
/// <summary>
/// nの乗法逆元n^{-1}を返す。計算量: O(1)
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public ModInt<T> Inverse(long n)
{
Debug.Assert(0 <= n && n < _inverse.Length);
return _inverse[n];
}
}
public sealed class AtCoderIO
{
Queue<string> _readQueue = new Queue<string>();
private void LoadQueue()
{
if (_readQueue.Count > 0) return;
string line = Console.ReadLine();
string[] split = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < split.Length; i++) _readQueue.Enqueue(split[i]);
}
private void Guard()
{
if (_readQueue.Count == 0)
{
throw new Exception("NO DATA TO READ");
}
}
public int Int()
{
LoadQueue();
Guard();
return int.Parse(_readQueue.Dequeue());
}
public long Long()
{
LoadQueue();
Guard();
return long.Parse(_readQueue.Dequeue());
}
public string String()
{
LoadQueue();
Guard();
return _readQueue.Dequeue();
}
public short Short()
{
LoadQueue();
Guard();
return short.Parse(_readQueue.Dequeue());
}
public byte Byte()
{
LoadQueue();
Guard();
return byte.Parse(_readQueue.Dequeue());
}
public char Char()
{
LoadQueue();
Guard();
return char.Parse(_readQueue.Dequeue());
}
public double Double()
{
LoadQueue();
Guard();
return double.Parse(_readQueue.Dequeue());
}
public float Float()
{
LoadQueue();
Guard();
return float.Parse(_readQueue.Dequeue());
}
public ModInt<T> ModInt<T>() where T : struct, IMod
{
return new ModInt<T>(Long());
}
public T Read<T>()
{
Type type = typeof(T);
if (type == typeof(int)) return (T)(object)Int();
else if (type == typeof(long)) return (T)(object)Long();
else if (type == typeof(float)) return (T)(object)Float();
else if (type == typeof(double)) return (T)(object)Double();
else if (type == typeof(short)) return (T)(object)Short();
else if (type == typeof(byte)) return (T)(object)Byte();
else if (type == typeof(char)) return (T)(object)Char();
else if (type == typeof(string)) return (T)(object)String();
else return default(T);
}
public int[] IntArray(int n)
{
if (n == 0) return Array.Empty<int>();
int[] arr = new int[n];
for (int i = 0; i < n; i++)
{
arr[i] = Int();
}
return arr;
}
public int[] ZeroIndexedPermutation(int n)
{
if (n == 0) return Array.Empty<int>();
int[] arr = new int[n];
for (int i = 0; i < n; i++)
{
arr[i] = Int() - 1;
}
return arr;
}
public long[] LongArray(int n)
{
if (n == 0) return Array.Empty<long>();
long[] arr = new long[n];
for (int i = 0; i < n; i++)
{
arr[i] = Long();
}
return arr;
}
public double[] DoubleArray(int n)
{
if (n == 0) return Array.Empty<double>();
double[] arr = new double[n];
for (int i = 0; i < n; i++)
{
arr[i] = Double();
}
return arr;
}
public ModInt<T>[] ModIntArray<T>(int n) where T : struct, IMod
{
if (n == 0) return Array.Empty<ModInt<T>>();
ModInt<T>[] arr = new ModInt<T>[n];
for (int i = 0; i < n; i++)
{
arr[i] = (ModInt<T>)Long();
}
return arr;
}
public T[] ReadArray<T>(int n)
{
if (n == 0) return Array.Empty<T>();
T[] arr = new T[n];
for (int i = 0; i < n; i++)
{
arr[i] = Read<T>();
}
return arr;
}
}
public static class Tmpl
{
public static long pow(long b, long exp)
{
if (exp == 0) return 1;
if (exp == 1) return b;
long m = pow(b, exp / 2L);
m *= m;
if (exp % 2L == 1) m *= b;
return m;
}
public static long modpow(long b, long exp, long mod)
{
if (exp == 0) return 1;
if (exp == 1) return b % mod;
long m = modpow(b, exp / 2L, mod);
m *= m;
m %= mod;
if (exp % 2L == 1) m *= b % mod;
m %= mod;
return m;
}
static long modinv( long a, long mod )
{
long b = mod, u = 1, v = 0;
while ( b > 0 )
{
long t = a / b;
a -= t * b; swap( ref a, ref b );
u -= t * v; swap( ref u, ref v );
}
u %= mod;
if (u < 0) u += mod;
return u;
}
public static long calcLcm(long a, long b)
{
return a * b / calcGcd(a, b);
}
public static long calcGcd(long a, long b)
{
if (a % b == 0) return b;
return calcGcd(b, a % b);
}
// ax ≡ b (mod m)なる最小のxを求める
public static bool solveModLinear(long a, long b, long m, out long minSolution)
{
long gcd = calcGcd(calcGcd(a, b), m);
a /= gcd;
b /= gcd;
m /= gcd;
if (calcGcd(a, m) == 1)
{
long inv = modinv(a, m);
minSolution = (b * inv) % m;
return true;
}
minSolution = 0;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void YesNo(bool t)
{
Console.WriteLine(t ? "Yes" : "No");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void YESNO(bool t)
{
Console.WriteLine(t ? "YES" : "NO");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void yesno(bool t)
{
Console.WriteLine(t ? "yes" : "no");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool checkBit(int bit, int n)
{
return ((1 << n) & bit) != 0;
}
public static bool nextSubset(ref int set, int super)
{
set = (set - 1) & super;
return set != 0;
}
public static bool nextCombination(int n, int r, int[] array)
{
int i = array.Length - 1;
while (i >= 0 && array[i] == i + n - r)
{
i--;
}
if (i < 0) return false;
array[i]++;
for (int j = i + 1; j < r; j++)
{
array[j] = array[j - 1] + 1;
}
return true;
}
public static bool nextPermutation<T>(T[] array, int start, int length) where T : IComparable<T>
{
int end = start + length - 1;
if (end <= start) return false;
int last = end;
while (true)
{
int pos = last--;
if (array[last].CompareTo(array[pos]) < 0)
{
int i;
for (i = end + 1; array[last].CompareTo(array[--i]) >= 0; ) { }
T tmp = array[last]; array[last] = array[i]; array[i] = tmp;
Array.Reverse(array, pos, end - pos + 1);
return true;
}
if (last == start)
{
Array.Reverse(array, start, end - start);
return false;
}
}
throw new Exception("NextPermutation: Fatal error");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool chmax<T> (ref T target, T value) where T : struct, IComparisonOperators<T, T, bool>
{
if (value > target)
{
target = value;
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool chmin<T>(ref T target, T value) where T : struct, IComparisonOperators<T, T, bool>
{
if (value < target)
{
target = value;
return true;
}
return false;
}
public static ReadOnlySpan<T> spanOf<T>(List<T> list)
{
return CollectionsMarshal.AsSpan(list);
}
public static int lowerBound<T>(T[] array, int start, int end, T value) where T : struct, IComparisonOperators<T, T, bool>
{
int low = start;
int high = end;
int mid;
while (low < high)
{
mid = ((high - low) >> 1) + low;
if (array[mid] < value)
low = mid + 1;
else
high = mid;
}
if (low == array.Length - 1 && array[low] < value)
{
return array.Length;
}
return low;
}
public static int lowerBound<T>(List<T> array, int start, int end, T value) where T : struct, IComparisonOperators<T, T, bool>
{
int low = start;
int high = end;
int mid;
while (low < high)
{
mid = ((high - low) >> 1) + low;
if (array[mid] < value)
low = mid + 1;
else
high = mid;
}
if (low == array.Count - 1 && array[low] < value)
{
return array.Count;
}
return low;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void swap<T>(ref T a, ref T b) where T : struct
{
T temp = a;
a = b;
b = temp;
}
public static int[] compressCoords<T>(T[] a) where T : struct, IComparisonOperators<T, T, bool>
{
T[] b = a.OrderBy(x => x).Distinct().ToArray();
int[] result = new int[a.Length];
for (int i = 0; i < a.Length; i++)
{
result[i] = lowerBound(b, 0, b.Length - 1, a[i]);
}
return result;
}
public static List<RunLengthElement<T>> compressRunLength<T>(T[] array) where T : struct, IEquatable<T>
{
List<RunLengthElement<T>> list = new List<RunLengthElement<T>>();
int count = 1;
int start = 0;
T prev = array[0];
for (int i = 1; i < array.Length; i++)
{
if (prev.Equals(array[i]))
{
count++;
}
else
{
list.Add(new RunLengthElement<T>(start, count, prev));
start = i;
count = 1;
}
prev = array[i];
}
list.Add(new RunLengthElement<T>(start, count, prev));
return list;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void print<T>(IEnumerable<T> array, char delimiter = ' ')
{
Console.WriteLine(string.Join(delimiter, array));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void fprint<T>(IEnumerable<T> array, char delimiter = ' ')
{
print(array);
Console.Out.Flush();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void print(string msg)
{
Console.WriteLine(msg);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void fprint(string msg)
{
Console.WriteLine(msg);
Console.Out.Flush();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void print(int val)
{
print(val.ToString());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void print(long val)
{
print(val.ToString());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void print<T>(ModInt<T> val) where T : struct, IMod
{
print(val.ToString());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void fprint(int val)
{
print(val.ToString());
Console.Out.Flush();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void fprint(long val)
{
print(val.ToString());
Console.Out.Flush();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void fprint<T>(ModInt<T> val) where T : struct, IMod
{
fprint(val.ToString());
Console.Out.Flush();
}
public static void print<T>(T[,] grid)
{
for (int y = 0; y < grid.GetLength(0); y++)
{
for (int x = 0; x < grid.GetLength(1); x++)
{
Console.Write(grid[y, x] + "\t");
}
Console.WriteLine();
}
}
public static void print01(bool t)
{
Console.WriteLine(t ? "1" : "0");
}
public static TSrc lowerBoundKth<TSrc, TCnt>(TSrc min, TSrc max, Func<TSrc, TCnt> f, TCnt bound)
where TSrc: struct, INumber<TSrc> where TCnt: struct, INumber<TCnt>
{
TSrc left = min;
TSrc right = max;
TSrc two = TSrc.CreateChecked(2);
TSrc one = TSrc.CreateChecked(1);
while (right > left)
{
TSrc mid = left + (right - left) / two;
TCnt c = f(mid);
if (c < bound)
{
left = mid + one;
}
else
{
right = mid;
}
}
return left;
}
public static bool isSquareNumber(long n)
{
long q = (long)Math.Floor(Math.Sqrt(n));
return q * q == n;
}
public static T[][] makeDPTable2D<T>(int length1, int length2, T value)
{
bool fill = !default(T).Equals(value);
T[][] table = new T[length1][];
for (int i = 0; i < length1; i++)
{
table[i] = new T[length2];
if (fill)
{
Array.Fill(table[i], value);
}
}
return table;
}
public static T[][][] makeDPTable3D<T>(int length1, int length2, int length3, T value)
{
bool fill = !default(T).Equals(value);
T[][][] table = new T[length1][][];
for (int i = 0; i < length1; i++)
{
table[i] = new T[length2][];
for (int j = 0; j < length2; j++)
{
table[i][j] = new T[length3];
if (fill)
{
Array.Fill(table[i][j], value);
}
}
}
return table;
}
}
public readonly struct RunLengthElement<T> where T : struct
{
public readonly int Count;
public readonly int StartIndex;
public readonly T Value;
public RunLengthElement(int startIndex, int count, T value)
{
this.StartIndex = startIndex;
this.Count = count;
this.Value = value;
}
}
/// <summary>
/// 自動でmodをとる整数。必要ないならあんまり使いすぎないように。
/// パフォーマンスはあまり良くないかもしれない。
/// </summary>
/// <typeparam name="T"></typeparam>
public readonly struct ModInt<T> : INumber<ModInt<T>>
where T : struct, IMod
{
public static long Mod => _mod.Mod;
private static readonly T _mod = default;
public readonly long Value;
/// <summary>
/// 1を返す。計算量: O(1)
/// </summary>
public static ModInt<T> One { get; } = CreateFast(1L);
/// <summary>
/// 0を返す。計算量: O(1)
/// </summary>
public static ModInt<T> Zero { get; } = CreateFast(0L);
public static int Radix => 10;
public static ModInt<T> MinValue => CreateFast(0L);
public static ModInt<T> MaxValue => CreateFast(_mod.Mod - 1);
/// <summary>
/// 加法単位元つまり0を返す。計算量: O(1)
/// </summary>
public static ModInt<T> AdditiveIdentity { get; } = CreateFast(0L);
public static ModInt<T> MultiplicativeIdentity { get; } = CreateFast(1L);
public ModInt(long value)
{
Value = SafeMod(value);
}
private ModInt(long value, bool dummy)
{
Value = value;
}
/// <summary>
/// modintを構築する。0 <= value < MODのとき限定。速いはず。計算量: O(1)
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ModInt<T> CreateFast(long value)
{
return new ModInt<T>(value, false);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static long SafeMod(long a)
{
return a % _mod.Mod + ((a >> 63) & _mod.Mod);
}
/// <summary>
/// exp乗を計算する。計算量: O(log(exp))
/// </summary>
/// <param name="exp"></param>
/// <returns></returns>
public readonly ModInt<T> Power(long exp)
{
if (exp < 0)
{
return Power(-exp).Inv();
}
else
{
long res = 1L;
long b = Value;
while (exp > 0)
{
if ((exp & 1) == 1) res = res * b % _mod.Mod;
b = b * b % _mod.Mod;
exp >>= 1;
}
return CreateFast(res);
}
}
/// <summary>
/// 乗法逆元を返す。0は渡さない。計算量: O(logN)
/// </summary>
/// <returns></returns>
public readonly ModInt<T> Inv()
{
long x = 1, y = 0;
long x1 = 0, y1 = 1;
long b = _mod.Mod;
long a = Value;
while (b != 0)
{
long q = a / b;
long t = a % b;
a = b;
b = t;
long tx = x - q * x1;
long ty = y - q * y1;
x = x1;
y = y1;
x1 = tx;
y1 = ty;
}
return new(x);
}
[MethodImpl(256)]
public static ModInt<T> operator +(ModInt<T> left, ModInt<T> right) => CreateFast((left.Value + right.Value) % _mod.Mod);
[MethodImpl(256)]
public static ModInt<T> operator +(ModInt<T> self) => self;
[MethodImpl(256)]
public static ModInt<T> operator -(ModInt<T> left, ModInt<T> right) => CreateFast((left.Value - right.Value + _mod.Mod) % _mod.Mod);
[MethodImpl(256)]
public static ModInt<T> operator -(ModInt<T> self) => CreateFast(_mod.Mod - self.Value);
[MethodImpl(256)]
public static ModInt<T> operator *(ModInt<T> left, ModInt<T> right) => CreateFast(left.Value * right.Value % _mod.Mod);
[MethodImpl(256)]
public static ModInt<T> operator /(ModInt<T> left, ModInt<T> right)
{
if (right.Value == 0L)
{
throw new DivideByZeroException();
}
ModInt<T> inv = right.Inv();
return CreateFast(left.Value * inv.Value % _mod.Mod);
}
public static ModInt<T> operator %(ModInt<T> left, ModInt<T> right)
{
throw new NotImplementedException();
}
public static bool operator <(ModInt<T> left, ModInt<T> right)
{
throw new NotImplementedException();
}
public static bool operator >(ModInt<T> left, ModInt<T> right)
{
throw new NotImplementedException();
}
public static bool operator <=(ModInt<T> left, ModInt<T> right)
{
throw new NotImplementedException();
}
public static bool operator >=(ModInt<T> left, ModInt<T> right)
{
throw new NotImplementedException();
}
[MethodImpl(256)]
public static bool operator ==(ModInt<T> left, ModInt<T> right) => left.Value == right.Value;
[MethodImpl(256)]
public static bool operator !=(ModInt<T> left, ModInt<T> right) => !(left == right);
[MethodImpl(256)]
public static ModInt<T> operator ++(ModInt<T> self) => CreateFast((self.Value + 1) % _mod.Mod);
[MethodImpl(256)]
public static ModInt<T> operator --(ModInt<T> self) => CreateFast((self.Value - 1 + _mod.Mod) % _mod.Mod);
[MethodImpl(256)]
public bool Equals(ModInt<T> other) => Value == other.Value;
[MethodImpl(256)]
public override bool Equals(object other)
{
if (other is ModInt<T> m)
{
return this == m;
}
else return false;
}
[MethodImpl(256)]
public override int GetHashCode() => Value.GetHashCode();
[MethodImpl(256)]
public static implicit operator ModInt<T>(long v) => new ModInt<T>(v);
[MethodImpl(256)]
public static implicit operator ModInt<T>(int v) => new ModInt<T>(v);
[MethodImpl(256)]
public static implicit operator long(in ModInt<T> m) => m.Value;
[MethodImpl(256)]
public static implicit operator int(in ModInt<T> m) => (int)m.Value;
public override string ToString() => Value.ToString();
public string ToString(string format, IFormatProvider provider) => Value.ToString(format, provider);
#region INumberBase<TSelf> Implementation
public static ModInt<T> Abs(ModInt<T> value) => value;
public static bool IsCanonical(ModInt<T> value) => true;
public static bool IsComplexNumber(ModInt<T> value) => false;
public static bool IsFinite(ModInt<T> value) => true;
public static bool IsImaginaryNumber(ModInt<T> value) => false;
public static bool IsInfinity(ModInt<T> value) => false;
public static bool IsInteger(ModInt<T> value) => true;
public static bool IsNaN(ModInt<T> value) => false;
public static bool IsNegative(ModInt<T> value) => false;
public static bool IsPositive(ModInt<T> value) => value.Value != 0L;
public static bool IsRealNumber(ModInt<T> value) => true;
public static bool IsZero(ModInt<T> value) => value.Value == 0L;
public static bool IsEvenInteger(ModInt<T> value) => (value.Value & 1) == 0;
public static bool IsOddInteger(ModInt<T> value) => (value.Value & 1) == 1;
public static bool IsPositiveInfinity(ModInt<T> value) => false;
public static bool IsNegativeInfinity(ModInt<T> value) => false;
public static bool IsNormal(ModInt<T> value) => false;
public static bool IsSubnormal(ModInt<T> value) => false;
public static ModInt<T> MaxMagnitude(ModInt<T> x, ModInt<T> y)
{
if (x.Value > y.Value) return x;
else return y;
}
public static ModInt<T> MaxMagnitudeNumber(ModInt<T> x, ModInt<T> y) => MaxMagnitude(x, y);
public static ModInt<T> MinMagnitude(ModInt<T> x, ModInt<T> y)
{
if (x.Value < y.Value) return x;
else return y;
}
public static ModInt<T> MinMagnitudeNumber(ModInt<T> x, ModInt<T> y) => MinMagnitude(x, y);
public static ModInt<T> CreateChecked<TOther>(TOther value) where TOther : INumberBase<TOther>
=> new(long.CreateChecked(value));
public static ModInt<T> CreateSaturating<TOther>(TOther value) where TOther : INumberBase<TOther>
=> new(long.CreateSaturating(value));
public static ModInt<T> CreateTruncating<TOther>(TOther value) where TOther : INumberBase<TOther>
=> new(long.CreateTruncating(value));
public static ModInt<T> Parse(string s, NumberStyles style, IFormatProvider provider) => Parse(s.AsSpan(), style, provider);
public static ModInt<T> Parse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider) => new(long.Parse(s, style, provider));
#if NET8_0_OR_GREATER
public static ModInt<T> Parse(ReadOnlySpan<byte> s, NumberStyles style, IFormatProvider provider) => new(long.Parse(s, style, provider));
#endif
public static ModInt<T> Parse(string s, IFormatProvider provider) => new(long.Parse(s, provider));
public static ModInt<T> Parse(ReadOnlySpan<char> s, IFormatProvider provider) => new(long.Parse(s, provider));
#if NET8_0_OR_GREATER
public bool TryFormat(Span<byte> dest, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider provider)
{
return Value.TryFormat(dest, out bytesWritten, format, provider);
}
#endif
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider provider)
{
return Value.TryFormat(destination, out charsWritten, format, provider);
}
public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider, out ModInt<T> result)
{
if (long.TryParse(s, style, provider, out long inner))
{
result = new(inner);
return true;
}
else
{
result = Zero;
return false;
}
}
public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out ModInt<T> result)
{
if (long.TryParse(s, style, provider, out long inner))
{
result = new(inner);
return true;
}
else
{
result = Zero;
return false;
}
}
public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider provider, out ModInt<T> result)
{
if (long.TryParse(s, provider, out long inner))
{
result = new(inner);
return true;
}
else
{
result = Zero;
return false;
}
}
public static bool TryParse(string s, IFormatProvider provider, out ModInt<T> result)
{
if (long.TryParse(s, provider, out long inner))
{
result = new(inner);
return true;
}
else
{
result = Zero;
return false;
}
}
public static bool TryConvertFromChecked<TOther>(TOther value, out ModInt<T> result) where TOther : INumberBase<TOther>
{
throw new NotImplementedException();
}
public static bool TryConvertFromSaturating<TOther>(TOther value, out ModInt<T> result) where TOther : INumberBase<TOther>
{
throw new NotImplementedException();
}
public static bool TryConvertFromTruncating<TOther>(TOther value, [MaybeNullWhen(false)] out ModInt<T> result) where TOther : INumberBase<TOther>
{
throw new NotImplementedException();
}
public static bool TryConvertToChecked<TOther>(ModInt<T> value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase<TOther>
{
throw new NotImplementedException();
}
public static bool TryConvertToSaturating<TOther>(ModInt<T> value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase<TOther>
{
throw new NotImplementedException();
}
public static bool TryConvertToTruncating<TOther>(ModInt<T> value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase<TOther>
{
throw new NotImplementedException();
}
#endregion
#region INumber<TSelf> Implementation
public int CompareTo(ModInt<T> other) => Value.CompareTo(other.Value);
public int CompareTo(object other) => Value.CompareTo(other);
#endregion
}
/// <summary>
/// 法を指定するやつ。
/// </summary>
public interface IMod
{
public long Mod { get; }
}
public readonly struct Mod998244353 : IMod { public long Mod => 998244353L; }
public readonly struct Mod1000000007 : IMod { public long Mod => 1000000007L; }
public readonly struct Mod897581057 : IMod { public long Mod => 897581057; }
public readonly struct Mod880803841 : IMod { public long Mod => 880803841; }
nauclhlt