結果
問題 | No.2023 Tiling is Fun |
ユーザー |
![]() |
提出日時 | 2022-07-29 21:57:06 |
言語 | C# (.NET 8.0.404) |
結果 |
AC
|
実行時間 | 62 ms / 2,000 ms |
コード長 | 37,863 bytes |
コンパイル時間 | 10,495 ms |
コンパイル使用メモリ | 166,864 KB |
実行使用メモリ | 198,900 KB |
最終ジャッジ日時 | 2024-07-19 14:37:03 |
合計ジャッジ時間 | 12,418 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 18 |
コンパイルメッセージ
復元対象のプロジェクトを決定しています... /home/judge/data/code/main.csproj を復元しました (89 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/
ソースコード
using System;using System.Buffers;using System.Collections.Generic;using System.Diagnostics;using System.IO;using System.Linq;using System.Numerics;using System.Runtime.CompilerServices;using System.Runtime.InteropServices;using System.Runtime.Intrinsics.X86;using System.Text;using YukicoderContest354.Problems;using ModInt = YukicoderContest354.Problems.ProblemC.StaticModInt<YukicoderContest354.Problems.ProblemC.Mod998244353>;namespace YukicoderContest354.Problems{public class ProblemC : ProblemBase{public ProblemC() : base(false) { }[MethodImpl(MethodImplOptions.AggressiveOptimization)]protected override void SolveEach(IOManager io){var a = io.ReadInt();var b = io.ReadInt();var comb = new ModCombination<Mod998244353>();io.WriteLine(comb.Combination(a + b - 2, a - 1));}#region ModInt/// <summary>/// コンパイル時に決定する mod を表します。/// </summary>/// <example>/// <code>/// public readonly struct Mod1000000009 : IStaticMod/// {/// public uint Mod => 1000000009;/// public bool IsPrime => true;/// }/// </code>/// </example>public interface IStaticMod{/// <summary>/// mod を取得します。/// </summary>uint Mod { get; }/// <summary>/// mod が素数であるか識別します。/// </summary>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;}/// <summary>/// 実行時に決定する mod の ID を表します。/// </summary>/// <example>/// <code>/// public readonly struct ModID123 : IDynamicModID { }/// </code>/// </example>public interface IDynamicModID { }public readonly struct ModID0 : IDynamicModID { }public readonly struct ModID1 : IDynamicModID { }public readonly struct ModID2 : IDynamicModID { }/// <summary>/// 四則演算時に自動で mod を取る整数型。mod の値はコンパイル時に決定している必要があります。/// </summary>/// <typeparam name="T">定数 mod を表す構造体</typeparam>/// <example>/// <code>/// using ModInt = AtCoder.StaticModInt<AtCoder.Mod1000000007>;////// void SomeMethod()/// {/// var m = new ModInt(1);/// m -= 2;/// Console.WriteLine(m); // 1000000006/// }/// </code>/// </example>public readonly struct StaticModInt<T> : IEquatable<StaticModInt<T>> where T : struct, IStaticMod{private readonly uint _v;/// <summary>/// 格納されている値を返します。/// </summary>public int Value => (int)_v;/// <summary>/// mod を返します。/// </summary>public static int Mod => (int)default(T).Mod;public static StaticModInt<T> Zero => new StaticModInt<T>();public static StaticModInt<T> One => new StaticModInt<T>(1u);/// <summary>/// <paramref name="v"/> に対して mod を取らずに StaticModInt<<typeparamref name="T"/>> 型のインスタンスを生成します。/// </summary>/// <remarks>/// <para>定数倍高速化のための関数です。 <paramref name="v"/> に 0 未満または mod 以上の値を入れた場合の挙動は未定義です。</para>/// <para>制約: 0≤|<paramref name="v"/>|<mod</para>/// </remarks>[MethodImpl(MethodImplOptions.AggressiveInlining)]public static StaticModInt<T> Raw(int v){var u = unchecked((uint)v);Debug.Assert(u < Mod);return new StaticModInt<T>(u);}/// <summary>/// StaticModInt<<typeparamref name="T"/>> 型のインスタンスを生成します。/// </summary>/// <remarks>/// <paramref name="v"/>が 0 未満、もしくは mod 以上の場合、自動で mod を取ります。/// </remarks>public StaticModInt(long v) : this(Round(v)) { }private StaticModInt(uint v) => _v = v;[MethodImpl(MethodImplOptions.AggressiveInlining)]private static uint Round(long v){var x = v % default(T).Mod;if (x < 0){x += default(T).Mod;}return (uint)x;}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static StaticModInt<T> operator ++(StaticModInt<T> value){var v = value._v + 1;if (v == default(T).Mod){v = 0;}return new StaticModInt<T>(v);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static StaticModInt<T> operator --(StaticModInt<T> value){var v = value._v;if (v == 0){v = default(T).Mod;}return new StaticModInt<T>(v - 1);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static StaticModInt<T> operator +(StaticModInt<T> lhs, StaticModInt<T> rhs){var v = lhs._v + rhs._v;if (v >= default(T).Mod){v -= default(T).Mod;}return new StaticModInt<T>(v);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static StaticModInt<T> operator -(StaticModInt<T> lhs, StaticModInt<T> rhs){unchecked{var v = lhs._v - rhs._v;if (v >= default(T).Mod){v += default(T).Mod;}return new StaticModInt<T>(v);}}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static StaticModInt<T> operator *(StaticModInt<T> lhs, StaticModInt<T> rhs){return new StaticModInt<T>((uint)((ulong)lhs._v * rhs._v % default(T).Mod));}/// <summary>/// 除算を行います。/// </summary>/// <remarks>/// <para>- 制約: <paramref name="rhs"/> に乗法の逆元が存在する。(gcd(<paramref name="rhs"/>, mod) = 1)</para>/// <para>- 計算量: O(log(mod))</para>/// </remarks>public static StaticModInt<T> operator /(StaticModInt<T> lhs, StaticModInt<T> rhs) => lhs * rhs.Inverse();public static StaticModInt<T> operator +(StaticModInt<T> value) => value;public static StaticModInt<T> operator -(StaticModInt<T> value) => new StaticModInt<T>() - value;public static bool operator ==(StaticModInt<T> lhs, StaticModInt<T> rhs) => lhs._v == rhs._v;public static bool operator !=(StaticModInt<T> lhs, StaticModInt<T> rhs) => lhs._v != rhs._v;public static implicit operator StaticModInt<T>(int value) => new StaticModInt<T>(value);public static implicit operator StaticModInt<T>(long value) => new StaticModInt<T>(value);/// <summary>/// 自身を x として、x^<paramref name="n"/> を返します。/// </summary>/// <remarks>/// <para>制約: 0≤|<paramref name="n"/>|</para>/// <para>計算量: O(log(<paramref name="n"/>))</para>/// </remarks>public StaticModInt<T> Pow(long n){Debug.Assert(0 <= n);var x = this;var r = Raw(1);while (n > 0){if ((n & 1) > 0){r *= x;}x *= x;n >>= 1;}return r;}/// <summary>/// 自身を x として、 xy≡1 なる y を返します。/// </summary>/// <remarks>/// <para>制約: gcd(x, mod) = 1</para>/// </remarks>[MethodImpl(MethodImplOptions.AggressiveInlining)]public StaticModInt<T> Inverse(){if (default(T).IsPrime){Debug.Assert(_v > 0);return Pow(default(T).Mod - 2);}else{var (g, x) = InternalMath.InvGCD(_v, default(T).Mod);Debug.Assert(g == 1);return new StaticModInt<T>(x);}}public override string ToString() => _v.ToString();public override bool Equals(object obj) => obj is StaticModInt<T> && Equals((StaticModInt<T>)obj);public bool Equals(StaticModInt<T> other) => Value == other.Value;public override int GetHashCode() => _v.GetHashCode();}/// <summary>/// 四則演算時に自動で mod を取る整数型。実行時に mod が決まる場合でも使用可能です。/// </summary>/// <remarks>/// 使用前に DynamicModInt<<typeparamref name="T"/>>.Mod に mod の値を設定する必要があります。/// </remarks>/// <typeparam name="T">mod の ID を表す構造体</typeparam>/// <example>/// <code>/// using AtCoder.ModInt = AtCoder.DynamicModInt<AtCoder.ModID0>;////// void SomeMethod()/// {/// ModInt.Mod = 1000000009;/// var m = new ModInt(1);/// m -= 2;/// Console.WriteLine(m); // 1000000008/// }/// </code>/// </example>public readonly struct DynamicModInt<T> : IEquatable<DynamicModInt<T>> where T : struct, IDynamicModID{private readonly uint _v;private static Barrett bt;/// <summary>/// 格納されている値を返します。/// </summary>public int Value => (int)_v;/// <summary>/// mod を返します。/// </summary>public static int Mod{get => (int)bt.Mod;set{Debug.Assert(1 <= value);bt = new Barrett((uint)value);}}/// <summary>/// <paramref name="v"/> に対して mod を取らずに DynamicModInt<<typeparamref name="T"/>> 型のインスタンスを生成します。/// </summary>/// <remarks>/// <para>定数倍高速化のための関数です。 <paramref name="v"/> に 0 未満または mod 以上の値を入れた場合の挙動は未定義です。</para>/// <para>制約: 0≤|<paramref name="v"/>|<mod</para>/// </remarks>[MethodImpl(MethodImplOptions.AggressiveInlining)]public static DynamicModInt<T> Raw(int v){var u = unchecked((uint)v);Debug.Assert(bt != null, $"使用前に {nameof(DynamicModInt<T>)}<{nameof(T)}>.{nameof(Mod)} プロパティに mod の値を設定してください。");Debug.Assert(u < Mod);return new DynamicModInt<T>(u);}/// <summary>/// DynamicModInt<<typeparamref name="T"/>> 型のインスタンスを生成します。/// </summary>/// <remarks>/// <para>- 使用前に DynamicModInt<<typeparamref name="T"/>>.Mod に mod の値を設定する必要があります。</para>/// <para>- <paramref name="v"/> が 0 未満、もしくは mod 以上の場合、自動で mod を取ります。</para>/// </remarks>public DynamicModInt(long v) : this(Round(v)) { }private DynamicModInt(uint v) => _v = v;[MethodImpl(MethodImplOptions.AggressiveInlining)]private static uint Round(long v){Debug.Assert(bt != null, $"使用前に {nameof(DynamicModInt<T>)}<{nameof(T)}>.{nameof(Mod)} プロパティに mod の値を設定してください。");var x = v % bt.Mod;if (x < 0){x += bt.Mod;}return (uint)x;}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static DynamicModInt<T> operator ++(DynamicModInt<T> value){var v = value._v + 1;if (v == bt.Mod){v = 0;}return new DynamicModInt<T>(v);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static DynamicModInt<T> operator --(DynamicModInt<T> value){var v = value._v;if (v == 0){v = bt.Mod;}return new DynamicModInt<T>(v - 1);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static DynamicModInt<T> operator +(DynamicModInt<T> lhs, DynamicModInt<T> rhs){var v = lhs._v + rhs._v;if (v >= bt.Mod){v -= bt.Mod;}return new DynamicModInt<T>(v);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static DynamicModInt<T> operator -(DynamicModInt<T> lhs, DynamicModInt<T> rhs){unchecked{var v = lhs._v - rhs._v;if (v >= bt.Mod){v += bt.Mod;}return new DynamicModInt<T>(v);}}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static DynamicModInt<T> operator *(DynamicModInt<T> lhs, DynamicModInt<T> rhs){uint z = bt.Mul(lhs._v, rhs._v);return new DynamicModInt<T>(z);}/// <summary>/// 除算を行います。/// </summary>/// <remarks>/// <para>- 制約: <paramref name="rhs"/> に乗法の逆元が存在する。(gcd(<paramref name="rhs"/>, mod) = 1)</para>/// <para>- 計算量: O(log(mod))</para>/// </remarks>public static DynamicModInt<T> operator /(DynamicModInt<T> lhs, DynamicModInt<T> rhs) => lhs * rhs.Inverse();public static DynamicModInt<T> operator +(DynamicModInt<T> value) => value;public static DynamicModInt<T> operator -(DynamicModInt<T> value) => new DynamicModInt<T>() - value;public static bool operator ==(DynamicModInt<T> lhs, DynamicModInt<T> rhs) => lhs._v == rhs._v;public static bool operator !=(DynamicModInt<T> lhs, DynamicModInt<T> rhs) => lhs._v != rhs._v;public static implicit operator DynamicModInt<T>(int value) => new DynamicModInt<T>(value);public static implicit operator DynamicModInt<T>(long value) => new DynamicModInt<T>(value);/// <summary>/// 自身を x として、x^<paramref name="n"/> を返します。/// </summary>/// <remarks>/// <para>制約: 0≤|<paramref name="n"/>|</para>/// <para>計算量: O(log(<paramref name="n"/>))</para>/// </remarks>public DynamicModInt<T> Pow(long n){Debug.Assert(0 <= n);var x = this;var r = Raw(1);while (n > 0){if ((n & 1) > 0){r *= x;}x *= x;n >>= 1;}return r;}/// <summary>/// 自身を x として、 xy≡1 なる y を返します。/// </summary>/// <remarks>/// <para>制約: gcd(x, mod) = 1</para>/// </remarks>[MethodImpl(MethodImplOptions.AggressiveInlining)]public DynamicModInt<T> Inverse(){var (g, x) = InternalMath.InvGCD(_v, bt.Mod);Debug.Assert(g == 1);return new DynamicModInt<T>(x);}public override string ToString() => _v.ToString();public override bool Equals(object obj) => obj is DynamicModInt<T> && Equals((DynamicModInt<T>)obj);public bool Equals(DynamicModInt<T> other) => Value == other.Value;public override int GetHashCode() => _v.GetHashCode();}/// <summary>/// Fast moduler by barrett reduction/// <seealso href="https://en.wikipedia.org/wiki/Barrett_reduction"/>/// </summary>public class Barrett{public uint Mod { get; private set; }private ulong IM;public Barrett(uint m){Mod = m;IM = unchecked((ulong)-1) / m + 1;}/// <summary>/// <paramref name="a"/> * <paramref name="b"/> mod m/// </summary>public uint Mul(uint a, uint b){ulong z = a;z *= b;if (!Bmi2.X64.IsSupported) return (uint)(z % Mod);var x = Bmi2.X64.MultiplyNoFlags(z, IM);var v = unchecked((uint)(z - x * Mod));if (Mod <= v) v += Mod;return v;}}public static class InternalMath{/// <summary>/// g=gcd(a,b),xa=g(mod b) となるような 0≤x<b/g の(g, x)/// </summary>/// <remarks>/// <para>制約: 1≤<paramref name="b"/></para>/// </remarks>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;}}public static long SafeMod(long x, long m){x %= m;if (x < 0) x += m;return x;}}public class ModCombination<T> where T : struct, IStaticMod{readonly StaticModInt<T>[] _factorials;readonly StaticModInt<T>[] _invFactorials;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();for (int i = _invFactorials.Length - 2; i >= 0; i--){_invFactorials[i] = _invFactorials[i + 1] * StaticModInt<T>.Raw(i + 1);}}public StaticModInt<T> Factorial(int n) => _factorials[n];public StaticModInt<T> InvFactorial(int n) => _invFactorials[n];public StaticModInt<T> Permutation(int n, int k) => _factorials[n] * _invFactorials[n - k];public StaticModInt<T> Combination(int n, int k) => _factorials[n] * _invFactorials[k] * _invFactorials[n - k];public StaticModInt<T> CombinationWithRepetition(int n, int k) => Combination(n + k - 1, k);public void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException();}#endregion}}namespace YukicoderContest354{internal class Program{static void Main(string[] args){IProblem question = new ProblemC();using var io = new IOManager(Console.OpenStandardInput(), Console.OpenStandardOutput());question.Solve(io);}}}#region Base Classnamespace YukicoderContest354.Problems{public interface IProblem{string Solve(string input);void Solve(IOManager io);}public abstract class ProblemBase : IProblem{protected bool HasMultiTestCases { get; }protected ProblemBase(bool hasMultiTestCases) => HasMultiTestCases = hasMultiTestCases;public string Solve(string input){var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(input));var outputStream = new MemoryStream();using var manager = new IOManager(inputStream, outputStream);Solve(manager);manager.Flush();outputStream.Seek(0, SeekOrigin.Begin);var reader = new StreamReader(outputStream);return reader.ReadToEnd();}public void Solve(IOManager io){var tests = HasMultiTestCases ? io.ReadInt() : 1;for (var t = 0; t < tests; t++){SolveEach(io);}}protected abstract void SolveEach(IOManager io);}}#endregion#region Utilsnamespace YukicoderContest354{public class IOManager : IDisposable{private readonly BinaryReader _reader;private readonly StreamWriter _writer;private bool _disposedValue;private byte[] _buffer = new byte[1024];private int _length;private int _cursor;private bool _eof;const char ValidFirstChar = '!';const char ValidLastChar = '~';public IOManager(Stream input, Stream output){_reader = new BinaryReader(input);_writer = new StreamWriter(output) { AutoFlush = false };}[MethodImpl(MethodImplOptions.AggressiveInlining)]private char ReadAscii(){if (_cursor == _length){_cursor = 0;_length = _reader.Read(_buffer);if (_length == 0){if (!_eof){_eof = true;return char.MinValue;}else{ThrowEndOfStreamException();}}}return (char)_buffer[_cursor++];}[MethodImpl(MethodImplOptions.AggressiveInlining)]public char ReadChar(){char c;while (!IsValidChar(c = ReadAscii())) { }return c;}[MethodImpl(MethodImplOptions.AggressiveInlining)]public string ReadString(){var builder = new StringBuilder();char c;while (!IsValidChar(c = ReadAscii())) { }do{builder.Append(c);} while (IsValidChar(c = ReadAscii()));return builder.ToString();}public int ReadInt() => (int)ReadLong();[MethodImpl(MethodImplOptions.AggressiveInlining)]public long ReadLong(){long result = 0;bool isPositive = true;char c;while (!IsNumericChar(c = ReadAscii())) { }if (c == '-'){isPositive = false;c = ReadAscii();}do{result *= 10;result += c - '0';} while (IsNumericChar(c = ReadAscii()));return isPositive ? result : -result;}[MethodImpl(MethodImplOptions.AggressiveInlining)]private Span<char> ReadChunk(Span<char> span){var i = 0;char c;while (!IsValidChar(c = ReadAscii())) { }do{span[i++] = c;} while (IsValidChar(c = ReadAscii()));return span.Slice(0, i);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public double ReadDouble() => double.Parse(ReadChunk(stackalloc char[32]));[MethodImpl(MethodImplOptions.AggressiveInlining)]public decimal ReadDecimal() => decimal.Parse(ReadChunk(stackalloc char[32]));public int[] ReadIntArray(int n){var a = new int[n];for (int i = 0; i < a.Length; i++){a[i] = ReadInt();}return a;}public long[] ReadLongArray(int n){var a = new long[n];for (int i = 0; i < a.Length; i++){a[i] = ReadLong();}return a;}public double[] ReadDoubleArray(int n){var a = new double[n];for (int i = 0; i < a.Length; i++){a[i] = ReadDouble();}return a;}public decimal[] ReadDecimalArray(int n){var a = new decimal[n];for (int i = 0; i < a.Length; i++){a[i] = ReadDecimal();}return a;}[MethodImpl(MethodImplOptions.AggressiveInlining)]public void Write<T>(T value) => _writer.Write(value.ToString());[MethodImpl(MethodImplOptions.AggressiveInlining)]public void WriteLine<T>(T value) => _writer.WriteLine(value.ToString());public void WriteLine<T>(IEnumerable<T> values, char separator){var e = values.GetEnumerator();if (e.MoveNext()){_writer.Write(e.Current.ToString());while (e.MoveNext()){_writer.Write(separator);_writer.Write(e.Current.ToString());}}_writer.WriteLine();}public void WriteLine<T>(T[] values, char separator) => WriteLine((ReadOnlySpan<T>)values, separator);public void WriteLine<T>(Span<T> values, char separator) => WriteLine((ReadOnlySpan<T>)values, separator);public void WriteLine<T>(ReadOnlySpan<T> values, char separator){for (int i = 0; i < values.Length - 1; i++){_writer.Write(values[i]);_writer.Write(separator);}if (values.Length > 0){_writer.Write(values[^1]);}_writer.WriteLine();}public void Flush() => _writer.Flush();[MethodImpl(MethodImplOptions.AggressiveInlining)]private static bool IsValidChar(char c) => ValidFirstChar <= c && c <= ValidLastChar;[MethodImpl(MethodImplOptions.AggressiveInlining)]private static bool IsNumericChar(char c) => ('0' <= c && c <= '9') || c == '-';private void ThrowEndOfStreamException() => throw new EndOfStreamException();protected virtual void Dispose(bool disposing){if (!_disposedValue){if (disposing){_reader.Dispose();_writer.Flush();_writer.Dispose();}_disposedValue = true;}}public void Dispose(){Dispose(disposing: true);GC.SuppressFinalize(this);}}public static class UtilExtensions{public static bool ChangeMax<T>(ref this T value, T other) where T : struct, IComparable<T>{if (value.CompareTo(other) < 0){value = other;return true;}return false;}public static bool ChangeMin<T>(ref this T value, T other) where T : struct, IComparable<T>{if (value.CompareTo(other) > 0){value = other;return true;}return false;}public static void SwapIfLargerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>{if (a.CompareTo(b) > 0){(a, b) = (b, a);}}public static void SwapIfSmallerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>{if (a.CompareTo(b) < 0){(a, b) = (b, a);}}public static void Sort<T>(this T[] array) where T : IComparable<T> => Array.Sort(array);public static void Sort<T>(this T[] array, Comparison<T> comparison) => Array.Sort(array, comparison);}public static class CollectionExtensions{private class ArrayWrapper<T>{#pragma warning disable CS0649public T[] Array;#pragma warning restore CS0649}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static Span<T> AsSpan<T>(this List<T> list){return Unsafe.As<ArrayWrapper<T>>(list).Array.AsSpan(0, list.Count);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static Span<T> GetRowSpan<T>(this T[,] array, int i){var width = array.GetLength(1);return MemoryMarshal.CreateSpan(ref array[i, 0], width);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static Span<T> GetRowSpan<T>(this T[,,] array, int i, int j){var width = array.GetLength(2);return MemoryMarshal.CreateSpan(ref array[i, j, 0], width);}[MethodImpl(MethodImplOptions.AggressiveInlining)]public static Span<T> GetRowSpan<T>(this T[,,,] array, int i, int j, int k){var width = array.GetLength(3);return MemoryMarshal.CreateSpan(ref array[i, j, k, 0], width);}public static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);public static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);public static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);public static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);}public static class SearchExtensions{private struct LowerBoundComparer<T> : IComparer<T> where T : IComparable<T>{public int Compare(T x, T y) => 0 <= x.CompareTo(y) ? 1 : -1;}private struct UpperBoundComparer<T> : IComparer<T> where T : IComparable<T>{public int Compare(T x, T y) => 0 < x.CompareTo(y) ? 1 : -1;}// https://trsing.hatenablog.com/entry/2019/08/27/211038public static int GetGreaterEqualIndex<T>(this ReadOnlySpan<T> span, T inclusiveMin) where T : IComparable<T> => ~span.BinarySearch(inclusiveMin, new UpperBoundComparer<T>());public static int GetGreaterThanIndex<T>(this ReadOnlySpan<T> span, T exclusiveMin) where T : IComparable<T> => ~span.BinarySearch(exclusiveMin, new LowerBoundComparer<T>());public static int GetLessEqualIndex<T>(this ReadOnlySpan<T> span, T inclusiveMax) where T : IComparable<T> => ~span.BinarySearch(inclusiveMax, new LowerBoundComparer<T>()) - 1;public static int GetLessThanIndex<T>(this ReadOnlySpan<T> span, T exclusiveMax) where T : IComparable<T> => ~span.BinarySearch(exclusiveMax, new UpperBoundComparer<T>()) - 1;public static int GetGreaterEqualIndex<T>(this Span<T> span, T inclusiveMin) where T : IComparable<T> => ((ReadOnlySpan<T>)span).GetGreaterEqualIndex(inclusiveMin);public static int GetGreaterThanIndex<T>(this Span<T> span, T exclusiveMin) where T : IComparable<T> => ((ReadOnlySpan<T>)span).GetGreaterThanIndex(exclusiveMin);public static int GetLessEqualIndex<T>(this Span<T> span, T inclusiveMax) where T : IComparable<T> => ((ReadOnlySpan<T>)span).GetLessEqualIndex(inclusiveMax);public static int GetLessThanIndex<T>(this Span<T> span, T exclusiveMax) where T : IComparable<T> => ((ReadOnlySpan<T>)span).GetLessThanIndex(exclusiveMax);public static int BoundaryBinarySearch(Predicate<int> predicate, int ok, int ng){while (Math.Abs(ok - ng) > 1){var mid = (ok + ng) / 2;if (predicate(mid)){ok = mid;}else{ng = mid;}}return ok;}public static long BoundaryBinarySearch(Predicate<long> predicate, long ok, long ng){while (Math.Abs(ok - ng) > 1){var mid = (ok + ng) / 2;if (predicate(mid)){ok = mid;}else{ng = mid;}}return ok;}public static BigInteger BoundaryBinarySearch(Predicate<BigInteger> predicate, BigInteger ok, BigInteger ng){while (BigInteger.Abs(ok - ng) > 1){var mid = (ok + ng) / 2;if (predicate(mid)){ok = mid;}else{ng = mid;}}return ok;}public static double BoundaryBinarySearch(Predicate<double> predicate, double ok, double ng, double eps = 1e-9, int loopLimit = 1000){var count = 0;while (Math.Abs(ok - ng) > eps && count++ < loopLimit){var mid = (ok + ng) * 0.5;if (predicate(mid)){ok = mid;}else{ng = mid;}}return (ok + ng) * 0.5;}public static double Bisection(Func<double, double> f, double a, double b, double eps = 1e-9, int loopLimit = 100){double mid = (a + b) / 2;var fa = f(a);if (fa * f(b) >= 0){throw new ArgumentException("f(a)とf(b)は異符号である必要があります。");}for (int i = 0; i < loopLimit; i++){var fmid = f(mid);var sign = fa * fmid;if (sign < 0){b = mid;}else if (sign > 0){a = mid;fa = fmid;}else{return mid;}mid = (a + b) / 2;if (Math.Abs(b - a) < eps){break;}}return mid;}}}#endregion