AtCoder が提供しているABC(AtCoder Beginner Contest)328 のB問題をC++とPythonで解いてみました。ABC328は、2023年11月11日21:00に実施されました。
AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。
B問題 11/11(Difficulty : 86)
問題はリンク先をご覧ください。
11月11日のようにゾロ目になっている日数を求めます。AtCoder Problems による Difficulty は 86 でした。
解答案
以下の2つの方針でゾロ目の日数を求めます。
- 日付がゾロ目になるのは、各月多くとも2日となります。その2日が条件を満たすか調べます。
- 月と日について、文字列に変換して文字種がひとつか全探索して調べます。
C++ プログラム例(ABC328B)
制約から $1 \leqq N \leqq 100$、$1 \leqq D_i \leqq 100$ となります。月または日が100になる場合、ゾロ目になりません。このため、各月のゾロ目になる日付は1桁の場合と2桁の場合で、たかだか2日しかありません。
以下の手順でソロ目となる日付の日数を求めます。
- 月が2桁の場合、その月自体がゾロ目になっていないと日付はゾロ目になりません(18行目)。それぞれの月に対して、以下を調べます。
- 日が1桁の場合、月が持つ数字と一致している日が $D_i$ 以下か調べます(22行目)。
- 日が2桁の場合も、同じように $D_i$ 以下か調べます(24行目)。
以下が、C++プログラムとなります。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> d(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> d[i];
}
int result = 0;
for (int i = 1; i <= n; ++i) {
if (i == 100) {
continue;
}
if ((i >= 10)&&(i / 10 != i % 10)) {
continue;
}
int day = i % 10;
if (day <= d[i]) {
++result;
if (day * 10 + i % 10 <= d[i]) {
++result;
}
}
}
cout << result << endl;
return 0;
}
文字列で判定するプログラムも紹介します。この場合、日付に使われている文字列の文字種が1種類か調べます。文字種は set コンテナを使いました(17、18行目)。月と日について全探索します。
前者と比較して、すっきりとプログラムが書けています。以下となります。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> d(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> d[i];
}
int result = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= d[i]; ++j) {
string date = to_string(i) + to_string(j);
set<char> s(date.begin(), date.end());
if (s.size() == 1) {
++result;
}
}
}
cout << result << endl;
return 0;
}
どちらも AC(Accepted=正しいプログラム)と判定されました。
Python プログラム例(ABC328B)
Python 版も基本的な考え方は同じです。C++の最初のプログラムは以下となります。
"""AtCoder Beginner Contest 328 B"""
n = int(input())
d = list(map(int, input().split()))
d.insert(0, 0)
result = 0
for i in range(1, n + 1):
if i == 100:
continue
if i >= 10 and i // 10 != i % 10:
continue
day = i % 10
if day <= d[i]:
result += 1
if day * 10 + i % 10 <= d[i]:
result += 1
print(result)
文字に変換して解くプログラムも紹介します。
"""AtCoder Beginner Contest 328 B"""
n = int(input())
d = list(map(int, input().split()))
d.insert(0, 0)
result = 0
for i in range(1, n + 1):
for j in range(1, d[i] + 1):
date = str(i) + str(j)
s = set(date)
if len(s) == 1:
result += 1
print(result)
こちらも「AC」と判定されました。
最後に
コンテストでは、前者のプログラムを提出しました。公式解説を読み、文字列で解く方が簡単なプログラムになることが分かり、文字列として解くプログラムも紹介しました。
整数の問題を文字列として解く類題として、ABC304B問題(解説記事)があります。
引き続き ABC の問題を紹介していきます。