B - FizzBuzz Sum Editorial by TumoiYorozu
この解説は、C++ に入門したばかりの中高生レベルを想定して、考察の方法、コードの書き方の解説をします。
プログラミングの入門では FizzBuzz 問題と呼ばれる練習問題がある。
今回はそれをアレンジした問題である。
入力例1では、1+2+4+7+8+11+13+14 を計算し、その答えである 60 を出力すれば良いことが分かる。 つまり、3でも5でも割り切れない数の合計を求めれば良い。
例えば x が 3で割り切れるかどうかは x を3で割った余りが 0 かどうかで判定すると良い。
ある x が「3でも5でも割り切れない」を判定するにはいくつか書き方がある。
入力例2の答えは 266,666,333,332 ≒ \(2.66 \times 10^{11}\) なので、間違った答えが出てしまいます。 このときは、-9,223,372,036,854,775,808~9,223,372,036,854,775,807 (約±900京、\(9\times 10^{18}\) くらい)の整数を扱える 例えば以下のように使います。 このコードは 0 以上 N 未満の整数の総和を求める事ができ、100000 と入力すると 正しく 4999950000 と計算できます。(ans を int のままで計算すると704982704になります) これを参考に、解いてみましょう。
例えば以下のようなコードの場合、入力例1,2は合うけど、WAになってしまいます。
実際の提出のリンクはこちら プログラムの間違いを直すために、ループの中に i を表示する命令を書いて、観察してみましょう。 このプログラムを実行すると、以下のような表示になります。 i が 15 の場合を行ってくれていませんでした。 これは、 次のヒントで、これを治す方法を解説します。
いくつかやり方がありますが、例えば i が 1から始まって、 N 以下にforの中身を変更する方法が一番シンプルです。 また、0以上 N+1 未満 と変更しても今回は動きます。 しかし、i=0 は本来は行うべきじゃないので、あまり良い書き方ではありません。 他には、for の()の中身は変えずに、ループの中で新しい変数 x を用意して、 i+1 を入れてループさせる方法もあります。 ヒント1: 入力例1を手計算で解くときの方針
ヒント2: 繰り返し文の復習
for (int i = 0; i < N; i++)
で N 回のループが書ける。 ヒント3: 割り切れるかどうか
ヒント4: if の判定の書き方
「3で割り切れない」かつ「5で割り切れない」
if (x%3 != 0 && x%5 != 0) {
3でも5でも割り切れないときの処理
}
ifをネスト編
if (x%3 != 0) {
if (x%5 != 0) {
3でも5でも割り切れないときの処理
}
}
ifを並列編
if (x%3 == 0) {
3で割り切れた時の処理。何も書かなくても良い
} else if (x%5 == 0) {
3で割り切れず5で割り切れた時の処理。何も書かなくても良い
} else {
3でも5でも割り切れないときの処理
}
ヒント5: 入力例 2 の答えが 378360980 になっちゃった
long long
型を使いましょう。#include<bits/stdc++.h>
using namespace std;
int main() {
int N;
cin >> N;
long long ans = 0;
for(int i = 0; i < N; i++){
ans += i;
}
cout << ans << endl;
}
ヒント6: 入力例1,2は合ってるけど、WAになってしまう
#include<bits/stdc++.h>
using namespace std;
int main() {
int N;
cin >> N;
long long ans = 0;
for(int i = 0; i < N; i++){
if (i%3 != 0 && i%5 != 0) {
ans += i;
}
}
cout << ans << endl;
}
#include<bits/stdc++.h>
using namespace std;
int main() {
int N;
cin >> N;
long long ans = 0;
for(int i = 0; i < N; i++){
cout << "i=" << i << endl;
if (i%3 != 0 && i%5 != 0) {
ans += i;
}
}
cout << ans << endl;
}
i=0
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10
i=11
i=12
i=13
i=14
60
for(int i = 0; i < N; i++)
と書くと、i が 0から始まって、 N 未満 までの数しかループを回してくれないからです。 ヒント7: ヒント6の対処法
for(int i = 1; i <= N; i++){
cout << "i=" << i << endl;
}
for(int i = 0; i < N+1; i++){
cout << "i=" << i << endl;
}
for(int i = 0; i < N; i++){
int x = i + 1;
cout << "x=" << x << endl;
}
解答コード
#include<bits/stdc++.h>
using namespace std;
int main() {
int N;
cin >> N;
long long ans = 0;
for(int i = 1; i <= N; i++){
if (i%3 != 0 && i%5 != 0) {
ans += i;
}
}
cout << ans << endl;
}
posted:
last update: