ABC122解説がしたかった
A - Double Helix
問題の通りに実装するだけ
using System; using System.IO; namespace Contest { class Program { public void Solve() { var sc = new Scanner(); string b = sc.Next(); if (b == "A") Console.WriteLine("T"); if (b == "T") Console.WriteLine("A"); if (b == "C") Console.WriteLine("G"); if (b == "G") Console.WriteLine("C"); } static void Main(string[] args) => new Program().Solve(); } }
B - ATCoder
for文でleftを0から|S|まで回す
[left,right)がACGT文字列を満たす間rightを増やす = S[right]がACGTじゃないならbreak
答えを更新
leftをrightにする
つまりやるだけ
using System; using System.IO; namespace Contest { class Program { public void Solve() { var sc = new Scanner(); var S = sc.Next(); int ans = 0; for (int left = 0; left < S.Length; left++) { if (C(S[left])) { int right; for (right = left + 1; right < S.Length; right++) { if (!C(S[right])) break; } ans = Math.Max(ans, right - left); left = right; } } Console.WriteLine(ans); } bool C(char c) => c == 'A' || c == 'T' || c == 'G' || c == 'C'; static void Main(string[] args) => new Program().Solve(); } }
C - GeT AC
sum[i]を[0,i)の'AC'の個数とする
[l-1,r-1]の'AC'の個数は
S[l-2...i-1]が'AC'ならsum[r] - sum[l]
じゃないならsum[r]-sum[l-1]
一文字目でACが成立することはありえないので上の条件分岐なしでsum[r] - sum[l]してよさそう
using System; using System.IO; using System.Text; namespace Contest { class Program { public void Solve() { var sc = new Scanner(); int N = sc.NextInt(); int Q = sc.NextInt(); string S = sc.Next(); var sum = new int[N + 1]; for (int i = 1; i < N; i++) { sum[i + 1] = sum[i]; if (S[i] == 'C' && S[i - 1] == 'A') { sum[i + 1]++; } } var sb = new StringBuilder(); for (int i = 0; i < Q; i++) { var l = sc.NextInt() - 1; if (l > 0 && S[l] == 'C' && S[l - 1] == 'A') l++; int r = sc.NextInt(); sb.AppendLine((sum[r] - sum[l]).ToString()); } Console.Write(sb.ToString()); } static void Main(string[] args) => new Program().Solve(); } }
D - We Like AGC
メモ化再帰
...i文字で2個前がj、1個前がk、一番後ろがlで何通りか
条件を満たさないパターンは0
using System; using System.IO; namespace Contest { class Program { private int Mod = 1000000007; private int[,,,] memo = new int[101, 4, 4, 4]; public void Solve() { var sc = new Scanner(); int N = sc.NextInt(); long ans = 0; //memoを全部-1で初期化 for (int i = 0; i <= N; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { for (int l = 0; l < 4; l++) { memo[i, j, k, l] = -1; } } } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { ans += C(N, i, j, k); ans %= Mod; } } } Console.WriteLine(ans); } int C(int index, int one, int two, int last) { //既に計算済み = memoが-1じゃないならmemoをそのまま返す if (memo[index, one, two, last] != -1) return memo[index, one, two, last]; if (index == 3) { if (Check(-1, one, two, last)) return 1; else return 0; } else { int res = 0; for (int i = 0; i < 4; i++) { if (Check(i, one, two, last)) { res += C(index - 1, i, one, two); res %= Mod; } } memo[index, one, two, last] = res; return res; } } //i,j,k,lがAGC文字列ならfalse //Aを0、Cを1、Gを2、Tを3とする bool Check(int i, int j, int k, int l) { if (i == 0 && j == 2 && k == 1) return false; if (i == 0 && j == 1 && k == 2) return false; if (i == 2 && j == 0 && k == 1) return false; if (i == 0 && j == 2 && l == 1) return false; if (i == 0 && k == 2 && l == 1) return false; if (j == 0 && k == 2 && l == 1) return false; if (j == 0 && k == 1 && l == 2) return false; if (j == 2 && k == 0 && l == 1) return false; return true; } static void Main(string[] args) => new Program().Solve(); } }
感想
Dで時間かかった
A 1:37 (1:37)
B 6:47 (5:10)
C 19:23 (12:36)
D 83:28 (64:05)