AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC216-F Max Sum Counting
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("2");
WillReturn.Add("3 1");
WillReturn.Add("1 2");
//2
}
else if (InputPattern == "Input2") {
WillReturn.Add("2");
WillReturn.Add("1 1");
WillReturn.Add("2 2");
//0
}
else if (InputPattern == "Input3") {
WillReturn.Add("20");
WillReturn.Add("1937 3980 2689 1208 3640 1979 581 2271 4229 3948 3708 1522 4161 4661 3797 96 3388 3395 2920 2247");
WillReturn.Add("4485 2580 174 1156 3770 3396 3558 3500 3494 479 269 3383 1230 1711 3545 3919 134 475 3796 1017");
//476
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
const int Hou = 998244353;
struct ABPairInfoDef
{
internal int A;
internal int B;
}
static void Main()
{
List<string> InputList = GetInputList();
int[] AArr = InputList[1].Split(' ').Select(pX => int.Parse(pX)).ToArray();
int[] BArr = InputList[2].Split(' ').Select(pX => int.Parse(pX)).ToArray();
int UB = AArr.GetUpperBound(0);
var ABPairInfoList = new List<ABPairInfoDef>();
for (int I = 0; I <= UB; I++) {
ABPairInfoDef WillAdd;
WillAdd.A = AArr[I];
WillAdd.B = BArr[I];
ABPairInfoList.Add(WillAdd);
}
ABPairInfoList = ABPairInfoList.OrderBy(pX => pX.A).ToList();
int MaxA = AArr.Max();
// 場合の数[Bの合計]なDP表
int[] DPArr = new int[MaxA + 1];
DPArr[0] = 1;
int Answer = 0;
for (int I = 0; I <= UB; I++) {
for (int J = MaxA; 0 <= J; J--) {
if (DPArr[J] == 0) continue;
int NewJ = J + ABPairInfoList[I].B;
if (NewJ > MaxA) continue;
DPArr[NewJ] += DPArr[J];
DPArr[NewJ] %= Hou;
// 解に計上
if (NewJ <= ABPairInfoList[I].A) {
Answer += DPArr[J];
Answer %= Hou;
}
}
}
Console.WriteLine(Answer);
}
}
解説
Aが3 1 4 1 5 9 2
Bが6 5 3 5 8 9 7
として、
AはMax
BはSum
を見るので、Aの昇順にソートします。
すると、Bを順に走査しつつ、
場合の数[Bの合計] をDPで更新すれば良いと分かります。
DPを更新したときのBの添字で、Aの値を参照して、
Aの方が大きかったら、解に計上してます。