{ }codelper
関数の定義引数64ビット整数P0355

玉がいちばん少なくてすむそろばん

b 進法のそろばんは、桁ごとに玉を 0 個から b - 1 個まで置いて数を表す。
ある数を b 進法のそろばんに置くときに必要な玉の数は、その数を b 進法で書いたときの各桁の数字をすべて足した値である。
たとえば 10 は 2 進法で 1010 なので玉が 2 個必要で、10 進法では 10 なので玉が 1 個必要である。
質問が q 個与えられる。
質問ごとに数 n と、そろばん k 個の進法が与えられる。
質問ごとに、n を置くときに玉がいちばん少なくてすむそろばんの進法と、その玉の数を出力せよ。
玉の数がいちばん少ないそろばんが複数あれば、その中で入力にいちばん先に書かれたそろばんを選ぶ。
数と進法を受け取って玉の数を返す関数を 1 つ作り、そろばんごとにその関数を呼んで解いてみよ。
ただし採点は出力だけを見るので、関数を作ったかどうかは確認できない。

入力
1 行目に q が与えられる。
続く q 行に質問が 1 行に 1 つずつ、n、k、そして進法 k 個が空白 1 つで区切られて与えられる。
1 ≤ q ≤ 1,000、1 ≤ n ≤ 1,000,000,000,000,000(10 の 15 乗)、1 ≤ k ≤ 8、進法は 2 以上 1,000 以下の整数で、同じ進法が何度も書かれることがある
出力
質問ごとに 1 行に、選んだそろばんの進法とその玉の数を空白 1 つで区切って出力
例 1 · stdin
3
10 3 2 3 10
5 2 4 2
10000000000 2 7 10
stdout
10 1
4 2
10 1
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

関数を定義する形は言語ごとに違います。
Python は def beads(n, b):、JS は function beads(n, b) { }、TS はこれに n: number と戻り値の型を書きます。
Java と C# はクラスの中に static int beads(long n, int b) のように型をすべて書き、C と C++ も型を書きます。
Craykon は beads(n, b) { … 返す total; } のように名前と引数だけを書きます。
定義と呼び出しの順番も違います。
C は、呼ぶ場所より上に関数か関数プロトタイプ(int beads(long long n, int b);)が必要です。
ないと gcc 14 と clang はコンパイルエラーを出し、gcc 11 は警告だけ出して先へ進みます。
Python は def が実行される前に呼ぶと NameError で止まります。
JS の function 宣言と Craykon の関数は下に書いても上から呼べますが、JS で const beads = (n, b) => … として作った関数は、その行より先に呼ぶと ReferenceError です。
数を引数として渡すと 8 つの言語すべてで値がコピーされるので、関数の中で n を 0 になるまで割っても、呼んだ側の n はそのままです。
落とし穴 1:C++ で引数を long long& n と書くと、コピーではなく呼んだ側の n そのものになります。
最初の呼び出しが n を 0 にしてしまい、例の 1 行目が 10 1 ではなく 3 0 になります。
落とし穴 2:n は 32 ビット整数に入りません。
C で引数を int n と書くと、渡すときに黙って切り捨てられ、例の 3 行目が 10 29 になります。
Java と C# は long を int の引数に渡すとコンパイルエラーで知らせてくれます。
落とし穴 3:合計を入れる変数を関数の外に置くと、呼び出しが終わっても値が残ります。
次の呼び出しが前の合計に続けて足すので、例の 1 行目が 2 2 になります。
関数の中で 0 から始まる変数を新しく作ります。
落とし穴 4:玉の数が同じときに <= で比べると、後に書かれたそろばんに変わります。
例の 2 行目が 4 2 ではなく 2 2 になります。
JS・TS には整数の割り算の演算子がないので、解答は余りを引いてから割ります((n - n % b) / b)。
Python は //、Craykon は 数学.商 を使います。

Pythonmain.py · 26 行
import sys  def beads(n, b):    """n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합)"""    total = 0    while n > 0:        total += n % b        n //= b          # 매개변수 n만 줄어든다. 부른 쪽의 수는 그대로다    return total  lines = sys.stdin.read().split("\n")q = int(lines[0])out = []for line in lines[1:q + 1]:    nums = list(map(int, line.split()))    n, bases = nums[0], nums[2:]    best_base = bases[0]    best = beads(n, best_base)    for b in bases[1:]:        count = beads(n, b)        if count < best:     # 같으면 먼저 적힌 주판을 그대로 둔다            best, best_base = count, b    out.append(f"{best_base} {best}")print("\n".join(out))
JavaScriptmain.js · 30 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[0]);const out = [];for (let i = 1; i <= q; i++) {  const nums = lines[i].trim().split(" ").map(Number);  const n = nums[0];  let bestBase = nums[2];  let best = beads(n, bestBase); // function 선언은 끌어올려져서 정의보다 먼저 부를 수 있다  for (let j = 3; j < nums.length; j++) {    const count = beads(n, nums[j]);    if (count < best) {      // 같으면 먼저 적힌 주판을 그대로 둔다      best = count;      bestBase = nums[j];    }  }  out.push(`${bestBase} ${best}`);}console.log(out.join("\n")); // n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합)function beads(n, b) {  let total = 0;  while (n > 0) {    const digit = n % b;    total += digit;    n = (n - digit) / b; // JS의 /는 소수를 내므로 나머지를 먼저 뺀다  }  return total;}
TypeScriptmain.ts · 32 行
import { readFileSync } from "node:fs"; // n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합)function beads(n: number, b: number): number {  let total = 0;  while (n > 0) {    const digit: number = n % b;    total += digit;    n = (n - digit) / b; // TS의 /는 소수를 내므로 나머지를 먼저 뺀다  }  return total;} const lines: string[] = readFileSync(0, "utf8").split("\n");const q: number = Number(lines[0]);const out: string[] = [];for (let i = 1; i <= q; i++) {  const nums: number[] = lines[i].trim().split(" ").map(Number);  const n: number = nums[0];  let bestBase: number = nums[2];  let best: number = beads(n, bestBase);  for (let j = 3; j < nums.length; j++) {    const count: number = beads(n, nums[j]);    if (count < best) {      // 같으면 먼저 적힌 주판을 그대로 둔다      best = count;      bestBase = nums[j];    }  }  out.push(`${bestBase} ${best}`);}console.log(out.join("\n"));
JavaMain.java · 39 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    // n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합). n은 int에 담기지 않아 long이다    static int beads(long n, int b) {        int total = 0;        while (n > 0) {            total += (int) (n % b);            n /= b;        }        return total;    }     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int q = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < q; i++) {            StringTokenizer st = new StringTokenizer(in.readLine());            long n = Long.parseLong(st.nextToken());            int k = Integer.parseInt(st.nextToken());            int bestBase = Integer.parseInt(st.nextToken());            int best = beads(n, bestBase);            for (int j = 1; j < k; j++) {                int b = Integer.parseInt(st.nextToken());                int count = beads(n, b);                if (count < best) { // 같으면 먼저 적힌 주판을 그대로 둔다                    best = count;                    bestBase = b;                }            }            out.append(bestBase).append(' ').append(best).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 42 行
using System;using System.Text; class Program{    // n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합). n은 int에 담기지 않아 long이다    static int Beads(long n, int b)    {        int total = 0;        while (n > 0)        {            total += (int)(n % b);            n /= b;        }        return total;    }     static void Main()    {        int q = int.Parse(Console.ReadLine().Trim());        var sb = new StringBuilder();        for (int i = 0; i < q; i++)        {            string[] parts = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            long n = long.Parse(parts[0]);            int bestBase = int.Parse(parts[2]);            int best = Beads(n, bestBase);            for (int j = 3; j < parts.Length; j++)            {                int b = int.Parse(parts[j]);                int count = Beads(n, b);                if (count < best) // 같으면 먼저 적힌 주판을 그대로 둔다                {                    best = count;                    bestBase = b;                }            }            sb.Append(bestBase).Append(' ').Append(best).Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 37 行
#include <iostream>using namespace std; // n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합).// n을 값으로 받으므로 여기서 줄여도 부른 쪽의 n은 그대로다int beads(long long n, int b) {    int total = 0;    while (n > 0) {        total += (int)(n % b);        n /= b;    }    return total;} int main() {    ios::sync_with_stdio(false);    cin.tie(nullptr);    int q;    cin >> q;    for (int i = 0; i < q; i++) {        long long n;        int k, bestBase;        cin >> n >> k >> bestBase;        int best = beads(n, bestBase);        for (int j = 1; j < k; j++) {            int b;            cin >> b;            int count = beads(n, b);            if (count < best) { // 같으면 먼저 적힌 주판을 그대로 둔다                best = count;                bestBase = b;            }        }        cout << bestBase << ' ' << best << '\n';    }    return 0;}
Cmain.c · 36 行
#include <stdio.h> /* 함수 원형: main보다 뒤에 정의하므로, 부르기 전에 생김새를 먼저 알려 준다 */int beads(long long n, int b); int main(void) {    int q;    scanf("%d", &q);    for (int i = 0; i < q; i++) {        long long n;        int k, best_base;        scanf("%lld %d %d", &n, &k, &best_base);        int best = beads(n, best_base);        for (int j = 1; j < k; j++) {            int b;            scanf("%d", &b);            int count = beads(n, b);            if (count < best) { /* 같으면 먼저 적힌 주판을 그대로 둔다 */                best = count;                best_base = b;            }        }        printf("%d %d\n", best_base, best);    }    return 0;} /* n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합) */int beads(long long n, int b) {    int total = 0;    while (n > 0) {        total += (int)(n % b);        n /= b; /* 값으로 받은 복사본만 줄어든다 */    }    return total;}
Craykonmain.cray · 32 行
q = コンソール.行読み().数に();繰り返す (i = 0; i < q; i++){    nums = コンソール.数読み();    n = nums[0];    bestBase = nums[2];    // 함수는 아래에 정의했지만 먼저 부를 수 있다    best = beads(n, bestBase);    繰り返す (j = 3; j < nums.個数; j++)    {        count = beads(n, nums[j]);        // 같으면 먼저 적힌 주판을 그대로 둔다        もし (count < best)        {            best = count;            bestBase = nums[j];        }    }    コンソール.書く(bestBase + " " + best);} // n을 b진법 주판에 올릴 때 드는 구슬 수(자리 숫자의 합)beads(n, b){    total = 0;    間 (n > 0)    {        total += n % b;        n = 数学.商(n, b);    }    返す total;}