各桁の合計が条件範囲内である整数の和を求める
AtCoderで練習問題を解いたのでそのときのメモです。
サンプル入力では正解の値が出るのに、提出するとなぜかWA(Wrong Answer)となってしまい、どこが間違っているのか探すのに苦労しました。
問題:
1以上N以下の整数のうち、10進法で各桁の和がA以上B以下であるものの総和を求めてください。
制約:
・1 ≦ N ≦ 10^4
・1 ≦ A ≦ B ≦ 36
・入力はすべて整数(AtCoder ABC083B-Some Sums より引用)
方針1
・各桁を0~9に増やしていくループを桁ごとに入れ子にする
・ループ内で整数の値を求め、条件に合致するか判定する
始めに思いついたのはこちらの方針でした。
//方針1
//10000の位を追加し忘れたためWAになっていた
#include <stdio.h>
int main(void)
{
//input
int h, i, j ,k, l, answer;
int n, a, b;
scanf("%d %d %d", &n, &a, &b);
answer = 0;
for (h = 0; 2 > h; h++) { //ここのループ(1万の位)を忘れていた!
for (i = 0; 10 > i; i++) {
for (j = 0; 10 > j; j++) {
for (k = 0; 10 > k; k++) {
for (l = 0; 10 > l; l++) {
if (a <= h+i+j+k+l && i+j+k+l <= b) {
if (h*10000 + i*1000 + j*100 + k*10 + l <= n) {
answer += h*10000 + i*1000 + j*100 + k*10 + l;
}
}
}
}
}
}
}
//output
printf("%d\n", answer);
return 0;
}
10^4(10の4乗)は10000なので5桁になりうる
制約にあるとおり範囲は1 ≦ N ≦ 10^4なのでn = 10000となることがありうるのですが、4桁の1000が最大だと思い込んでいたようです。
ループを追加すると解決しました。
方針2
・判定する整数を1~Nまで順に増やす一重のループにする
・ループ内で各桁の値を求めて条件に合致するか判定する
方針2の方がループも少なくて済むのでスムーズに見えます。
また、桁数の和を求めるときにi/10000...
とすべきところをn/10000...
と書き間違えており、ループの意味がないというミスがありました。nをiに書き直すと解決しました。
整数Nの10のx乗の位は(N%10^(x+1)/10^x
で求める
例) 千の位なら (n%10000)/1000
#include <stdio.h>
int main(void)
{
//input
int n, a, b;
int sum, i, keta;
scanf("%d %d %d", &n, &a, &b);
sum = 0;
for (i = 0; n >= i; i++) {
keta = i/10000 + (i%10000)/1000 + (i%1000)/100 + (i%100)/10 + i%10;
// ↑↑↑ 書き間違えに注意!
if (a <= keta && keta <= b) {
sum += i;
}
}
//output
printf("%d", sum);
return 0;
}
2022/10/6実施
2022/10/7修正
参照先:AtCoder
今後の課題
・出てくる変数が増えてきても落ち着いて把握すること
・制約をしっかり読み、漏れなく場合分けをすること