AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC425-E Count Sequences 2
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("3 1000000000");
WillReturn.Add("2");
WillReturn.Add("2 2");
WillReturn.Add("5");
WillReturn.Add("1 1 1 1 1");
WillReturn.Add("6");
WillReturn.Add("1 2 3 4 5 6");
//6
//120
//230379200
}
else if (InputPattern == "Input2") {
WillReturn.Add("3 998244353");
WillReturn.Add("1");
WillReturn.Add("1");
WillReturn.Add("3");
WillReturn.Add("4 2 5");
WillReturn.Add("10");
WillReturn.Add("500 500 500 500 500 500 500 500 500 500");
//1
//6930
//261233246
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long[] GetSplitArr(string pStr)
{
return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
}
static long Hou;
static long[][] mPascalSankakukeiJagArr;
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = (pStr) => wkArr = GetSplitArr(pStr);
SplitAct(InputList[0]);
Hou = wkArr[1];
mPascalSankakukeiJagArr = CreatePascalSankakukeiJagArr(5000, Hou);
for (int I = 2; I <= InputList.Count - 1; I += 2) {
long[] CArr = GetSplitArr(InputList[I]);
long Result = Solve(CArr);
Console.WriteLine(Result);
}
}
static long Solve(long[] pCArr)
{
long SumCnt = pCArr.Sum();
long Answer = 1;
foreach (long EachC in pCArr) {
Answer *= mPascalSankakukeiJagArr[SumCnt][EachC];
SumCnt -= EachC;
Answer %= Hou;
}
return Answer;
}
// パスカルの三角形のジャグ配列を返す
// 引数1 (0始まりの)木の高さ上限
// 引数2 法
// 戻り値 ジャグ配列
// [0][0] 1
// [1][0から1] 1 1
// [2][0から2] 1 2 1
// [3][0から3] 1 3 3 1
// [4][0から4] 1 4 6 4 1
static long[][] CreatePascalSankakukeiJagArr(long pDepth, long pHou)
{
long[][] JagArr = new long[pDepth + 1][];
for (long I = 0; I <= pDepth; I++) {
JagArr[I] = new long[I + 1];
long CurrUB = JagArr[I].GetUpperBound(0);
JagArr[I][0] = 1;
JagArr[I][CurrUB] = 1;
if (I > 0) {
for (long J = 1; J < CurrUB; J++) {
long AddVal1 = JagArr[I - 1][J - 1];
long AddVal2 = JagArr[I - 1][J];
JagArr[I][J] = AddVal1 + AddVal2;
JagArr[I][J] %= pHou;
}
}
}
return JagArr;
}
}
解説
1が1個
2が2個
3が3個
□□□□□□
に順番に埋めていくと考えれば
1C6 * 2C5 * 3C3
で通り数を求めることができます。
chooseを高速で求めるために、
パスカルの三角形を最初に作成してます。