はじめに
AtCoder Beginner Contest 262の復習記事です。
記事におけるScanner
クラスは、自作の入力クラスです。
コンテスト
https://atcoder.jp/contests/abc262
問題A
Y
が4の倍数
ならば2年後、Y
が4の倍数+1
ならば1年後、Y
が4の倍数+2
ならばその年、Y
が4の倍数+3
ならば3年後が答えとなります。
Y
を4で割った余りが4の倍数+n
のn
なので、その値によって答えを求めます。
public static void Solve()
{
var Y = Scanner.Scan<int>();
var answer = Y;
if (Y % 4 == 0) answer += 2;
if (Y % 4 == 1) answer += 1;
if (Y % 4 == 3) answer += 3;
Console.WriteLine(answer);
}
問題B
U
とV
間に辺があるかどうかを二次元配列G
で表現し、G[a,b]
、G[b,c]
、G[c,a]
のすべてに辺が存在するときの総数を数え上げます。
public static void Solve()
{
var (N, M) = Scanner.Scan<int, int>();
var G = new bool[N, N];
for (var i = 0; i < M; i++)
{
var (u, v) = Scanner.Scan<int, int>();
u--;
v--;
G[u, v] = G[v, u] = true;
}
var answer = 0;
for (var a = 0; a < N; a++)
{
for (var b = a + 1; b < N; b++)
{
for (var c = b + 1; c < N; c++)
{
if (G[a, b] && G[b, c] && G[c, a]) answer++;
}
}
}
Console.WriteLine(answer);
}
問題C
条件となるi
とj
を全探索してしまうと、時間計算量がO(N^2)
となり、実行時間制限内に答えを求めることはできません。
条件を満たす要素を考えてみると、(i==A[i], j==A[j])
と(i==A[j], j==A[i])
となる組み合わせが対象となります。
前者の場合、[1, x, x, 4, 5]
のようなA
があったとすると、(1,4)
、(1,5)
、(4,5)
が答えとなり、i==A[i]
となる要素から2つ選ぶ組み合わせとなるので、i==A[i]
の個数をC
とすると、C*(C-1)/2
が前者の組み合わせの数となります。
一方、後者の場合、i<j
よりA[i]>i
かつA[A[i]]==i
となるものがペアとして成り立ち、その総和が後者の組み合わせの数となります。
よって、これらの総和が答えとなります。
N
が最大5*10^5
なので、int
では収まらないので注意が必要です。
public static void Solve()
{
var N = Scanner.Scan<int>();
var A = Scanner.ScanEnumerable<int>().Select(x => x - 1).ToArray();
var answer = 0L;
var same = 0L;
for (var i = 0; i < N; i++)
{
if (A[i] == i) same++;
else if (A[i] > i && A[A[i]] == i) answer++;
}
answer += same * (same - 1) / 2;
Console.WriteLine(answer);
}
問題D
A
の項を選ぶ個数を1つ決めたときの和の余りを動的計画法で求め、全て求めたときのあまりが0
の数の1
からN
までの総和が答えとなります。
public static void Solve()
{
var N = Scanner.Scan<int>();
var A = Scanner.ScanEnumerable<long>().ToArray();
mint answer = 0;
for (var c = 1; c <= N; c++)
{
var dp = new mint[N + 1, N + 1, N];
dp[0, 0, 0]++;
for (var i = 0; i < N; i++)
{
for (var j = 0; j < N; j++)
{
for (var k = 0; k < N; k++)
{
dp[i + 1, j + 1, (k + A[i]) % c] += dp[i, j, k];
dp[i + 1, j, k] += dp[i, j, k];
}
}
}
answer += dp[N, c, 0];
}
Console.WriteLine(answer);
}