Editorial for 第3回卬高杯 A問題 - Relabeling


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Authors: admin, RenCoda3

ヒント

難しいと思った場合(入出力の方法が分からない場合) 「競プロ 入出力 方法 (プログラミング言語)」と探せば、基本的な入出力の方法が分かるかと思います。
また競技プログラミングに慣れていない方は、別の初心者に向けられた問題も探すと良いと思います。
また、別の本校工学部員が「共通テスト形式」という、共通テスト形式で出題される問題が別にあります。サンプルプログラムが問題中に提示されるため、そちらも参考にしてみてください。
共通テスト形式の問題へのアクセスはコチラ→A問題/ B問題

概説

この問題では、問題文の通り、最も\(A\)に近い正の\(N\)の倍数を出力すれば正答となります。では、これを求めるためにはどのようにすれば良いでしょうか。
ここで候補になるのは、\(kN ≤ A < (k+1)N \quad (k=0,1,2 ...)\)を満たすような \(kN\) と \((k+1)N\) の2つです。この時の\(k\)は\(A\)を\(N\)で割った商と同値です。

\(k=0\)のとき

\(kN=0\) となり、\(kN\) は正の \(N\) の倍数ではないため、\((k+1)N\) すなわち \(N\) が答えとなります。

\(k>0\)のとき

\(A\)を\(N\)で割った時の余りを\(B\)とするとき、

  • \(B < \frac{N}{2}\) ならば \(kN\)
  • \(B = \frac{N}{2}\) ならば \(kN\) および \((k+1)N\)
  • \(B > \frac{N}{2}\) ならば \((k+1)N\)

が答えとなります。\(\frac{N}{2}\)は \(N\) が奇数のとき必ず整数ではないため、\(B=\frac{N}{2}\) となるようなことはなく、答えは1つの値に絞られます。これは簡単な演算と条件分岐によって実装することができます。

Pythonでは、整数同士の割り算は小数に直されますが、C++では、整数同士の割り算の結果は整数で出力され、小数点以下は切り捨てられます(「型キャスト」と検索すると詳しい話が出てきます)。 例えば、\(23 \div 5\) をPythonとC++で計算した場合、Pythonでの計算結果は \(5.75\) となりますが、C++での計算結果は \(4\) となります。 このため、\((A \div N)\times N\) の計算結果が必ずしも \(A\) と等しくなるとは限らないので、注意してください。


実装例

実装例(C++)
#include <bits/stdc++.h>
using namespace std;

int main(){
  int N, A; cin >> N >> A;
  int B = A % N;
  if(A/N==0){
    cout << N;
  }
  else{
    if(B<=N/2){ // B<N/2 とすると、例えばN=5,A=7のとき10と出力してしまいWAとなる
      cout << (A/N)*N << endl;
    }
    else{
      cout << (A/N+1)*N << endl;
    }
  }
}
実装例(Python)
N=int(input())
A=int(input())
B=A%N
if int(A/N)==0:
  print(N)
else:
  if B<N/2:
    print(int(A/N)*N)
  else:
    print(int(A/N+1)*N)

# A/N が小数として計算されているので、
# int(A/N)として小数点以下を切り捨ててもらう
# 6行目の N/2 は小数として扱われているので、
# C++の実装例の様に<=としなくても正しく計算できる

補足(元ネタ)

  • 特に\(A=5\)の時の処理は「スウェディッシュ・ラウンディング」または「現金端数処理」と呼ばれ、硬貨の最小額が5(単位は「オーレ」、補助通貨)となったスウェーデンから始まった端数処理の方法です。現在もいくつかの国でこの方法が利用されています。
  • ちなみに、現在スウェーデンでは、既に1クローナが現金の最小額となっているため、この方法は行われていません。


Comments

There are no comments at the moment.