1 ≤ n ≤ 10、2 ≤ b_i ≤ 60、0 ≤ d_i < b_i、-10^12 ≤ t ≤ 10^12(すべて整数)
出力
一行目:n 個の輪の目、二行目:越えた回数(後ろなら負)
例 1 · stdin
3
24 60 60
23 59 50
15
stdout
0 0 5
1
例 2 · stdin
2
7 3
0 1
-5
stdout
5 2
-1
main.py
エラー一覧00F8 ↓ · ⇧F8 ↑
入力(stdin)
実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。
$ 準備完了
コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。
ほかの言語では?言語別の解答を見る · 8 言語の解答
いちばん右の輪から、入ってきた値 s = d +(受け取った値)を、目 s mod b と左へ渡す商に分ければよいです。 後ろに回すと s が負になり、言語によって % と / が違います。 Python の %・// は切り捨て除算なので、目はいつも 0 ~ b-1、商も下に丸めた値(-4 // 3 == -2)で、そのまま正しいです。 C・C++・Java・C#・JS・TS・Craykon の % は割られる数の符号に従い(-4 % 3 == -1)、C・C++・Java・C# の整数の /、JS・TS の Math.trunc(s / b)、Craykon の 数学.商 は 0 の方へ切り捨てる(-4 / 3 == -1)ので、目が負になり、借りが一つ足りなくなります。 JS・TS・Craykon の / は小数まで割る(-4 / 3 == -1.333…)ので、そのまま商には使えません。 (s % b + b) % b で目を直してから、商は (s - 目) / b で求めるか(ちょうど割り切れます)、Java なら Math.floorMod・Math.floorDiv を使います。 目だけ直して商を 0 の方へ切り捨てる割り算のままにするのもよくある間違いです。 二つ目の落とし穴は大きさです。 t は 10^12 までなので C・C++ は long long、Java・C# は long が必要で、int に入れるとあふれます。 JS・TS・Craykon の数は 2^53(約 9×10^15)まで正確なので t は大丈夫です。 しかしカウンター全体を一つの数に直して計算すると、輪の目の数の積が 60^10(約 6×10^17)まで大きくなって 2^53 を超え、下の桁が狂います。 輪ごとに余りと商で渡せば、どの言語でも値は t の近くにとどまります。 Python の int(s / b) も実数の割り算のあと 0 の方へ切り捨てるので同じ落とし穴です。
Pythonmain.py · 14 行
n = int(input())b = list(map(int, input().split()))d = list(map(int, input().split()))t = int(input())# 오른쪽 바퀴부터: 이 바퀴에 들어온 값 s를 칸(나머지)과 왼쪽으로 넘길 값(몫)으로 나눈다# Python의 %와 //는 내림 나눗셈이라 s가 음수여도 칸은 0 ~ b-1, 몫은 아래로 내린 값이다carry = tfor i in range(n - 1, -1, -1): s = d[i] + carry d[i] = s % b[i] carry = s // b[i]print(*d)print(carry) # 맨 왼쪽 바퀴에서도 넘친 값 = 계수기 전체가 넘어간 횟수
JavaScriptmain.js · 13 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const b = lines[1].trim().split(/\s+/).map(Number);const d = lines[2].trim().split(/\s+/).map(Number);let carry = Number(lines[3]); // 10^12는 2^53 안이라 Number로 정확하다// JS의 %는 나누어지는 수의 부호를 따른다(-7 % 3 === -1) → b를 더해 다시 나눈다for (let i = n - 1; i >= 0; i--) { const s = d[i] + carry; d[i] = ((s % b[i]) + b[i]) % b[i]; carry = (s - d[i]) / b[i]; // s - 칸은 b로 딱 나누어떨어진다: 내림 몫}console.log(d.join(" ") + "\n" + carry);
TypeScriptmain.ts · 14 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const b: number[] = lines[1].trim().split(/\s+/).map(Number);const d: number[] = lines[2].trim().split(/\s+/).map(Number);let carry: number = Number(lines[3]); // 10^12는 2^53 안이라 number로 정확하다// TS(JS)의 %는 나누어지는 수의 부호를 따른다(-7 % 3 === -1) → b를 더해 다시 나눈다for (let i = n - 1; i >= 0; i--) { const s: number = d[i] + carry; d[i] = ((s % b[i]) + b[i]) % b[i]; carry = (s - d[i]) / b[i]; // s - 칸은 b로 딱 나누어떨어진다: 내림 몫}console.log(d.join(" ") + "\n" + carry);
JavaMain.java · 24 行
import java.util.Scanner;public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] b = new int[n]; long[] d = new long[n]; for (int i = 0; i < n; i++) b[i] = sc.nextInt(); for (int i = 0; i < n; i++) d[i] = sc.nextLong(); long carry = sc.nextLong(); // 10^12: int로는 넘친다 // Java의 %와 /는 0 쪽으로 버린다(-7 % 3 == -1) → Math.floorMod·floorDiv는 내림으로 나눈다 for (int i = n - 1; i >= 0; i--) { long s = d[i] + carry; d[i] = Math.floorMod(s, (long) b[i]); carry = Math.floorDiv(s, (long) b[i]); } StringBuilder out = new StringBuilder(); for (int i = 0; i < n; i++) out.append(i > 0 ? " " : "").append(d[i]); out.append('\n').append(carry).append('\n'); System.out.print(out); }}
C#Main.cs · 23 行
using System;using System.Linq;class Program{ static void Main() { int n = int.Parse(Console.ReadLine()); int[] b = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); long[] d = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToArray(); long carry = long.Parse(Console.ReadLine().Trim()); // 10^12: int로는 넘친다 // C#의 %는 나누어지는 수의 부호를 따른다(-7 % 3 == -1) → b를 더해 다시 나눈다 for (int i = n - 1; i >= 0; i--) { long s = d[i] + carry; d[i] = (s % b[i] + b[i]) % b[i]; carry = (s - d[i]) / b[i]; // s - 칸은 b로 딱 나누어떨어진다: 내림 몫 } Console.WriteLine(string.Join(" ", d)); Console.WriteLine(carry); }}
C++main.cpp · 21 行
#include <iostream>#include <vector>int main() { int n; std::cin >> n; std::vector<long long> b(n), d(n); for (auto& x : b) std::cin >> x; for (auto& x : d) std::cin >> x; long long carry; // t는 10^12까지: int로는 넘친다 std::cin >> carry; // C++의 %는 0 쪽으로 버린 나눗셈의 나머지라 음수가 나올 수 있다 → b를 더해 다시 나눈다 for (int i = n - 1; i >= 0; i--) { long long s = d[i] + carry; d[i] = (s % b[i] + b[i]) % b[i]; carry = (s - d[i]) / b[i]; // s - 칸은 b로 딱 나누어떨어진다: 내림 몫 } for (int i = 0; i < n; i++) std::cout << (i ? " " : "") << d[i]; std::cout << '\n' << carry << '\n';}
Cmain.c · 20 行
#include <stdio.h>int main(void) { int n, b[10]; long long d[10], carry; /* t는 10^12까지: int로는 넘친다 */ scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &b[i]); for (int i = 0; i < n; i++) scanf("%lld", &d[i]); scanf("%lld", &carry); /* C의 %는 0 쪽으로 버린 나눗셈의 나머지라 음수가 나올 수 있다 → b를 더해 다시 나눈다 */ for (int i = n - 1; i >= 0; i--) { long long s = d[i] + carry; d[i] = (s % b[i] + b[i]) % b[i]; carry = (s - d[i]) / b[i]; /* s - 칸은 b로 딱 나누어떨어진다: 내림 몫 */ } for (int i = 0; i < n; i++) printf(i ? " %lld" : "%lld", d[i]); printf("\n%lld\n", carry); return 0;}
Craykonmain.cray · 15 行
n = コンソール.行読み().数に();b = コンソール.数読み();d = コンソール.数読み();carry = コンソール.行読み().数に(); // 10^12는 2^53 안이라 정확하다// 크레이콘의 %도 나누어지는 수의 부호를 따른다(-7 % 3 == -1) → b를 더해 다시 나눈다// 수학.몫은 0 쪽으로 버리니, 내림 몫은 (s - 칸) / b로 구한다(딱 나누어떨어진다)繰り返す (i = n - 1; i >= 0; i--){ s = d[i] + carry; d[i] = (s % b[i] + b[i]) % b[i]; carry = (s - d[i]) / b[i];}コンソール.書く(d.つなぐ(" "));コンソール.書く(carry);