はじめに
AtCoder Beginner Contest 318の復習記事です。
記事におけるScanner
クラスは、自作の入力クラスです。
Scannerクラス
public static class Scanner
{
public static T Scan<T>() where T : IConvertible => Convert<T>(ScanStringArray()[0]);
public static (T1, T2) Scan<T1, T2>() where T1 : IConvertible where T2 : IConvertible
{
var input = ScanStringArray();
return (Convert<T1>(input[0]), Convert<T2>(input[1]));
}
public static (T1, T2, T3) Scan<T1, T2, T3>() where T1 : IConvertible where T2 : IConvertible where T3 : IConvertible
{
var input = ScanStringArray();
return (Convert<T1>(input[0]), Convert<T2>(input[1]), Convert<T3>(input[2]));
}
public static (T1, T2, T3, T4) Scan<T1, T2, T3, T4>() where T1 : IConvertible where T2 : IConvertible where T3 : IConvertible where T4 : IConvertible
{
var input = ScanStringArray();
return (Convert<T1>(input[0]), Convert<T2>(input[1]), Convert<T3>(input[2]), Convert<T4>(input[3]));
}
public static (T1, T2, T3, T4, T5) Scan<T1, T2, T3, T4, T5>() where T1 : IConvertible where T2 : IConvertible where T3 : IConvertible where T4 : IConvertible where T5 : IConvertible
{
var input = ScanStringArray();
return (Convert<T1>(input[0]), Convert<T2>(input[1]), Convert<T3>(input[2]), Convert<T4>(input[3]), Convert<T5>(input[4]));
}
public static (T1, T2, T3, T4, T5, T6) Scan<T1, T2, T3, T4, T5, T6>() where T1 : IConvertible where T2 : IConvertible where T3 : IConvertible where T4 : IConvertible where T5 : IConvertible where T6 : IConvertible
{
var input = ScanStringArray();
return (Convert<T1>(input[0]), Convert<T2>(input[1]), Convert<T3>(input[2]), Convert<T4>(input[3]), Convert<T5>(input[4]), Convert<T6>(input[5]));
}
public static IEnumerable<T> ScanEnumerable<T>() where T : IConvertible => ScanStringArray().Select(Convert<T>);
private static string[] ScanStringArray()
{
var line = Console.ReadLine()?.Trim() ?? string.Empty;
return string.IsNullOrEmpty(line) ? Array.Empty<string>() : line.Split(' ');
}
private static T Convert<T>(string value) where T : IConvertible => (T)System.Convert.ChangeType(value, typeof(T));
}
コンテスト
https://atcoder.jp/contests/abc318
コンテスト提出
N
日間のうちM
日目以降の期間はN-M
日間であり、この期間にFloor(N-M)/P
回満月を見ることができます。
これにM
日目を加えた、Floor(N-M)/P+1
が答えとなります。
N-M
が負数になることがあるので注意が必要です。
コンテスト提出
シートは最大でも0<=x<=100
かつ0<=y<=100
なので、100*100
のグリッドを用意し、その領域がシートで覆われているかを判定します。
コンテスト提出
周遊パスは好きな日に使うことができるので、F
をソートしても問題ありません。
次のような動的計画法を解きます。
遷移は次のようになります。
i+D
がN
より大きい場合はN
にまとめることができ、dp[N]
が答えとなります。
コンテスト提出
次のような動的計画法を解きます。
遷移は次のようになります。
全ての頂点集合のうち、総和の最大値が答えとなります。
復習提出
L[x]
を現在左側にあるx
の個数、R[x]
を現在右側にあるx
の個数とします。
j
を固定したとき、j
に対して条件を満たすi,k
の組み合わせの個数は、1<=y<=N
かつy!=A[j]
のL[y]*R[y]
の総和になります。
これにより、各j
に対して時間計算量O(N)
で組み合わせの個数を求めることができますが、全体時間計算量がO(N^2)
になり、実行時間制限に間に合いません。
そこで、j
を1つずらしたとき、L[A[j]]
が1つ増え、R[A[j]]
が1つ減ることから、組み合わせの個数を累積和として管理し、各j
における差分のみを計算することで、各j
に対して時間計算量O(1)
で組み合わせの個数を求めることができるようになり、全体時間計算量O(N)
で答えを求めることができます。