こんにちは!
seiです!今回はAtCoder始めてちょうど一か月たったので、
パナソニックグループプログラミングコンテスト2023(AtCoder Beginner Contest 301)のコンテストレビューです!
結論から言うと爆死しました(笑)
コンテストに参加するのは今回で3回目になります。
結果
結果は8問中2問でした!
A問題を一回間違えて、C問題すら解けない有様でした(´;ω;`)
おいおい前回より下がってるぞ!
C問題は2個だけテストケースが通らなくて謎でした…
改善点
まず、B問題まで解くのに46分もかかっているので、これはもっと早く解く必要がありますね。
水色コーダーを目指すのであれば、C問題までを30分で解けるようになるのが目安のようです。
解くのに時間がかかっているのもそうですが、デバッグとテストケースのテストに時間がかかっていると思ったので、
この機会にVSCode環境を整備しました!
詳しくは以下の記事をご覧ください↓
こんにちは!seiです! 今日はAtCoder始めて結構時間がたったので、C++のおすすめ環境構築を紹介します。 初心者はこれで大分快適になるはずです! 他に便利なものがあればどんどんアップデートしていきますので、コメントいた[…]
A,B,C,D問題の解説
初心者だからこそわかりやすく説明できるのではと思って解説します。
※初心者のコード解説なんて誰トクなんだって感じですが(笑)
ぼくは、まずはA,B,C問題を確実に解くことを目標にしています。
D以上は難しくて時間かかりそうなので、時間をとってゆっくりやっています。
A問題の解答コード
https://atcoder.jp/contests/abc301/tasks/abc301_a
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, aP = 0, tP = 0;
string s;
cin >> n >> s;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'T')
{
tP++;
}
else if (s[i] == 'A')
{
aP++;
}
}
if (tP - aP > 0)
{
cout << "T" << endl;
}
else if (tP - aP < 0)
{
cout << "A" << endl;
}
else if (tP - aP == 0)
{
if (s[s.size() - 1] == 'A')
{
cout << "T" << endl;
}
else
{
cout << "A" << endl;
}
}
return 0;
}
これは言われた通りやるだけですね。
ポイントが同じときは一番最後の要素でポイント獲得したほうじゃない人が勝ちです。
間違った提出はにポイント獲得したindexをそれぞれ記録していたのですが、何個かのテストケースでダメでした…(記録に使った初期値が0でindexの開始数字と同じだったため)
初期値がfor文のインデックスの開始と同じときは気を付けないとですね…
B問題の解答コード
https://atcoder.jp/contests/abc301/tasks/abc301_b
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, a[110];
cin >> n;
vector<int> ans;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n - 1; i++)
{
if (abs(a[i + 1] - a[i]) == 1)
{
ans.push_back(a[i]);
}
else if (a[i + 1] > a[i])
{
int num = a[i + 1] - a[i];
for (int j = 0; j < num; j++)
{
ans.push_back(a[i] + j);
}
}
else if (a[i] > a[i + 1])
{
int num = a[i] - a[i + 1];
for (int j = 0; j < num; j++)
{
ans.push_back(a[i] - j);
}
}
}
ans.push_back(a[n - 1]);
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i] << " ";
}
cout << endl;
return 0;
}
これも言われたとおりやるだけなんですが、かなり冗長になってしまいました。
for (int i = 0; i < a.size()-1; i++)と書いていたら、aの要素数が変わっても反映されるみたいですね…
これを踏まえてすっきり書くと以下のようになります。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < a.size() - 1; i++)
{
if (a[i] + 1 < a[i + 1])
a.insert(a.begin() + i + 1, a[i] + 1);
if (a[i] - 1 > a[i + 1])
a.insert(a.begin() + i + 1, a[i] - 1);
}
for (int i = 0; i < a.size(); i++)
cout << a[i] << " ";
return 0;
}
C問題の解答コード
https://atcoder.jp/contests/abc301/tasks/abc301_c
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s, t;
cin >> s >> t;
map<char, int> left, right;
for (int i = 'a'; i <= 'z'; i++)
{
left[i] = 0;
right[i] = 0;
}
left['@'] = 0;
right['@'] = 0;
for (int i = 0; i < s.size(); i++)
{
left[s[i]] += 1;
right[t[i]] += 1;
}
for (int i = 'a'; i <= 'z'; i++)
{
if (left[i] == right[i])
continue;
else
{
if (i == 'a' || i == 't' || i == 'c' || i == 'o' || i == 'd' || i == 'e' || i == 'r')
{
// ちゃんと数字は明示してあげる必要がある。>0を省略する事はできない
if (left[i] - right[i] > 0)
{
right['@'] -= left[i] - right[i];
}
else if (right[i] - left[i] > 0)
{
left['@'] -= right[i] - left[i];
}
}
else
{
right['@'] = -100;
left['@'] = -100;
break;
}
}
}
if (right['@'] >= 0 && left['@'] >= 0)
{
cout << "Yes" << endl;
}
else
{
cout << "No" << endl;
}
return 0;
}
@と英小文字の個数をそれぞれの文字列で数えた後に比較してます。
atcoderのいずれの文字でもなく、文字数が違っていたら@で置き換えられないのでNo
atcoderの文字で最大限置き換え切った後に、両方の文字列の@の個数がマイナスだったら
@が足りなかったということなのでNoを出力してます。
本番通らなかったやつを改善したやつです。
本番通らなかった原因はif (left[i] – right[i])と書いていたからでした泣
if (left[i] – right[i] > 0)とちゃんと書いてあげる必要があります。
true,falseは判定してくれるので、良いと思っていました(´;ω;`)
D問題の解答コード
https://atcoder.jp/contests/abc301/tasks/abc301_d
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long int n;
long long init = 0;
string s;
cin >> s >> n;
vector<int> canChange;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == '?')
canChange.push_back(i);
if (s[i] == '1')
{
init += (long long)pow(2, s.size() - 1 - i) * 1;
}
}
if (init > n)
{
cout << "-1" << endl;
return 0;
}
for (int i = canChange.size() - 1; i >= 0; --i)
{
long long in = init;
init += (long long)pow(2, s.size() - 1 - canChange[i]);
if (init <= n)
{
continue;
}
else
{
init = in;
}
}
cout << init << endl;
return 0;
}
今回のDはそんなに難しくなかったので、解きたかったです。
C問題通らなくてずっと粘っていたので反省です。
上の桁から順にすでに確定している数字を読みに行きます。?1?なら2^1の位が1なのでinitに2*1を足します。
全部の桁を見終わった後に目標の数字nよりinitがデカかったら終了で、-1です。
また、この時?になっている桁のindexを記録します。
n以下の場合、先ほど記録したindexを用いて、上の桁から順に?になっている桁を見て、1に変えてみてnより大きくなるか調べます。
nより大きくならない場合initに足していきます。
最終的に足していったinitを出力すれば答えです!
提出で通らなかった原因
テストケース2個だけ通らなかったのですが、
powは戻り値にdouble型を返すので、しっかりキャストしてあげる必要がありました(´;ω;`)
まとめ
今回は>0を付けなかったり、型をきちんと考え切れてなかったりでうまくいきませんでした。
来週からはこの反省を活かして、ロジックがあっていそうなときは型を疑う癖をつけようと思います!