【緑】ABC397
こんにちは.tokidasakanaです.AtCoder Beginner Contest 397の自分の結果をまとめます.
結果
tokidasakanaさんのオムロンプログラミングコンテスト2025(AtCoder Beginner Contest 397)での成績:2355位
パフォーマンス:1166相当
レーティング:801→846 (+45) :)
Highestを更新しました!
A-Dの4完でした.まだレートが下がったことがないので,この調子であげていこうと思います.
A問題(100点)
- 問題文(要約)
がX 以上なら38.0 ,1 以上37.5 未満なら38.0 ,2 未満なら37.5 を出力せよ3 - 制約
30 \leq X \leq 50 -
は少数第X 位まで与えられる1
自分のコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
double x; cin >> x;
if (x >= 38.0) cout << 1;
else if (x >= 37.5) cout << 2;
else cout << 3;
cout << '\n';
return 0;
}
問題文の通りにやるだけでした.ちゃんとdouble
型の正しい処理をしないと不正解になると思います.知らんけど.
B問題(250点)
-
問題文(要約)
i
,o
のみからなる文字列 が与えられます.S の任意の位置に文字をS 文字以上挿入することで,変更後の文字列が以下の条件を満たすようにしたいです.0 - 長さが偶数であり,奇数文字目が
i
で偶数文字目がo
である.
挿入する必要のある文字数の最小値を求めて下さい.
- 長さが偶数であり,奇数文字目が
-
制約
-
はS i
,o
からなる長さ 以上1 以下の文字列100
-
自分のコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s; cin >> s;
vector<char> t;
for (char c : s) {
int cnt = t.size() + 1;
if (cnt % 2 == 1) {
if (c == 'o') t.push_back('i');
t.push_back(c);
} else {
if (c == 'i') t.push_back('o');
t.push_back(c);
}
}
if (t.size() % 2 == 1) t.push_back('o');
cout << t.size() - s.size() << '\n';
return 0;
}
おそらく想定解法は,
自分は
やり方は置いておくにしても,vector
を使用する必要はありませんでした.無駄な構造やライブラリは使用しないように心掛けているので,少し反省.
というわけで以下のコードでも正解しました.
#include <bits/stdc++.h>
using namespace std;
using ll = __int128_t;
string s, t;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> s;
for (char c : s) {
int cnt = t.size() + 1;
if (cnt % 2 == 1) {
if (c == 'o') t += 'i';
t += 'o';
} else {
if (c == 'i') t += 'o';
t += 'i';
}
}
if (t.size() % 2 == 1) t += 'o';
cout << t.size() - s.size() << '\n';
return 0;
}
C問題(350点)
-
問題文(要約)
長さ の整数列N が与えられます.A = (A_1, A_2, ... , A_N)
をA か所で区切って1 個の空でない連続する部分列に分割するとき,数列に含まれる数の種類数の和としてありえる最大値を求めてください.2 -
制約
2 \leq N \leq 3 \times 10^5 1 \leq A_i \leq N (1 \leq i \leq N) - 入力はすべて整数
自分のコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n, a[3<<17];
int sm[2][3<<17];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
set<int> s, t;
for (int i = 0; i < n; i++) {
cin >> a[i];
s.insert(a[i]);
sm[0][i] = s.size();
}
for (int i = n - 1; i >= 0; i--) {
t.insert(a[i]);
sm[1][i] = t.size();
}
int ans = 0;
for (int i = 1; i <= n - 1; i++) {
ans = max(ans, sm[0][i - 1] + sm[1][i]);
// cout << sm[0][i - 1] << sm[1][i] << '\n';
}
cout << ans << '\n';
return 0;
}
set
を使用したので,計算量は
左右それぞれから種類数を累積する配列を用意し,区切る箇所の左右で配列を見ればよいです.
具体的には以下のように考えました(入力例
配列名 | 中身 |
---|---|
[3, 1, 4, 1, 5] | |
[1, 2, 3, 3, 4] | |
[4, 3, 3, 2, 1] |
種類数は重複をカウントしないようにset
を使いましたが,これも別の配列で管理できるので不要だということがあとでわかりました(
D問題(425点)
- 問題文
正整数 が与えられます.N を満たす正整数の組x^3 - y^3 = N が存在するか判定し,存在する場合はそのような(x, y) を一つ出力してください.(ない場合は(x, y) -1
を出力) - 制約
1 \leq N \leq 10^{18} - 入力はすべて整数
自分のコード
#include <bits/stdc++.h>
using namespace std;
using ll = __int128_t;
long n;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
n = (ll)n;
for (ll k = 1; k * k * k <= 4 * n; k++) {
ll t2 = 3 * k * (4 * n - k * k * k);
for (ll t = (ll)sqrt(t2) - 1; t <= (ll)sqrt(t2) + 1; t++) {
if ((t - 3 * k * k) % (6 * k) == 0) {
ll y = (t - 3 * k * k) / (6 * k);
ll x = y + k;
if (y == 0 || x == 0) continue;
if ((x - y) * (x * x + x * y + y * y) == n) {
cout << (long)x << ' ' << (long)y << '\n';
return 0;
}
}
}
}
cout << -1 << '\n';
return 0;
}
計算量は
まずは以下のように変形しました.
そして,
これで
コード上では,for
文上で
ここで当たった壁がオーバーフローです.単純にこれらは数値によっては
解答では二分探索を行っていました.たしかによく考えてみれば二分探索できれいにかける気がしました.コンテスト中は冷静ではいられません.
感想
今回は配点がおかしいものの,C問題350点までを比較的早くとったのでD問題を余裕もって考えることができました.ゆえの4完だったと思います.途中でE問題も見ましたができそうになかったので,D問題を集中して考えました.目標は水色,できるなら一回も下がらずに到達したいです.
Discussion