サイコロ遊びを何回か行う。 一回の遊びには n 人がいて、1 番から n 番まで順に回りながら一回ずつ番をする(n 番の次はまた 1 番)。 みんな 0 点から始める。 サイコロは決まった規則で数を作る装置で、一回の遊びの全員が一つを一緒に使う。 サイコロには今の値 x が入っている。 振るたびに x を (a × x + c) を m で割った余りに変え、変わった x を 6 で割った余りに 1 を足したものが出た目である。 一人の番では次のことをする。 1. サイコロを一回振り、出た目を今回の番の合計に足す。 2. 出た目が 6 で、今回の番に振った回数が 3 より少なければ 1 に戻る。 3. 今回の番に 6 が三回出たら(振った三回がすべて 6 なら)、今回の番の合計は 0 になる。 4. 今回の番の合計をその人の点数に足す。 点数が G 以上になったらその人が勝ち、その遊びは終わる。 勝ったかどうかは番が終わった後にだけ見る。 したがって番では少なくとも一回は振る。 T 番目の番が終わっても勝った人がいなければ、その遊びは勝者なしで終わる。 一行目に遊びの回数 t、続く t 行に遊びごとに n、G、T、最初の x、a、c、m が空白一つずつを挟んで与えられる。 遊びごとに二行を出力せよ。 一行目には勝った人の番号(勝者がいなければ 0)、過ぎた番の数、サイコロを振った回数を空白一つずつ区切って書く。 二行目には 1 番から n 番までの点数を空白一つずつ区切って書く。
入力
1 ≤ t ≤ 50、1 ≤ n ≤ 8、1 ≤ G ≤ 10,000、1 ≤ T ≤ 10,000、すべての遊びの T の合計 ≤ 100,000。 1 ≤ m ≤ 1,000,000、0 ≤ 最初の x、a、c < m(整数)
出力
遊びごとに二行
例 1 · stdin
2
2 15 20 1 9 10 19
1 5 3 5 1 0 7
stdout
1 11 15
15 10
0 3 9
0
main.py
エラー一覧00F8 ↓ · ⇧F8 ↑
入力(stdin)
実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。
$ 準備完了
コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。
ほかの言語では?言語別の解答を見る · 8 言語の解答
一回の番が「まず振って、それからもっと振るかを聞く」形なので、do-while がぴったりです。 Java・C#・C・C++・JavaScript・TypeScript は do { 振る } while (face == 6 && count < 3); と書き、do-while のない Python は while True: の中で振ってから最後に if not (...): break、Craykon は 間 (真) { … もし (!(…)) { 抜ける; } }(韓国語で 동안 (참) { … 만약 (!(…)) { 그만; } })と書きます。 落とし穴は四つ:① do-while を普通の while (face == 6 && count < 3) に変えると入る前に先に聞くので、まだ振っていない face(0)では一回も振りません。 ② a × x は 10^12 まで大きくなります。 C・C++・Java・C# で int のまま掛けるとあふれて(C・C++ は未定義動作、Java・C# は黙って回り込み負になることもあります)目がおかしくなります。 long long・long で掛けます。 Python の int は限りがなく、JS・TS・Craykon の数は 2^53(約 9×10^15)まで正確なので 10^12 は大丈夫です。 ③ 6 が三回出たらそこで止まって 0 点です。 count <= 3 だと四回目を振り、0 点の処理を忘れると 18 点を足します。 ループが終わった後に最後の目が 6 なら三回とも 6 だったということなので、if (face == 6) 一行で分かります。 ④ 勝ったかどうかは番が終わった後にだけ見ます。 振るたびに点数と合計を足して G と比べると、6・6・6 で 0 点になる番でも勝ったことにしてしまいます。
Pythonmain.py · 34 行
import syslines = sys.stdin.read().split("\n")t = int(lines[0])out = []for line in lines[1 : t + 1]: n, goal, max_turns, x, a, c, m = map(int, line.split()) scores = [0] * n winner = 0 turns = 0 rolls = 0 player = 0 while turns < max_turns and winner == 0: turns += 1 turn_sum = 0 count = 0 # Python에는 do-while이 없다: while True로 들어가 끝에서 멈출지 묻는다(첫 굴림은 언제나 한다) while True: x = (a * x + c) % m face = x % 6 + 1 rolls += 1 count += 1 turn_sum += face if not (face == 6 and count < 3): break if face == 6: # 세 번 모두 6이면 이번 차례는 0점 turn_sum = 0 scores[player] += turn_sum if scores[player] >= goal: winner = player + 1 player = (player + 1) % n out.append(f"{winner} {turns} {rolls}") out.append(" ".join(map(str, scores)))print("\n".join(out))
JavaScriptmain.js · 27 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const t = Number(lines[0]);const out = [];for (let g = 1; g <= t; g++) { // a * x는 10^12까지라 number(2^53까지 정확)로 충분하다 let [n, goal, maxTurns, x, a, c, m] = lines[g].trim().split(" ").map(Number); const scores = new Array(n).fill(0); let winner = 0, turns = 0, rolls = 0, player = 0; while (turns < maxTurns && winner === 0) { turns++; let turnSum = 0, count = 0, face; do { // 첫 굴림은 언제나 한다 x = (a * x + c) % m; face = (x % 6) + 1; rolls++; count++; turnSum += face; } while (face === 6 && count < 3); if (face === 6) turnSum = 0; // 세 번 모두 6 scores[player] += turnSum; if (scores[player] >= goal) winner = player + 1; player = (player + 1) % n; } out.push(`${winner} ${turns} ${rolls}`, scores.join(" "));}console.log(out.join("\n"));
TypeScriptmain.ts · 30 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const t: number = Number(lines[0]);const out: string[] = [];for (let g = 1; g <= t; g++) { // a * x는 10^12까지라 number(2^53까지 정확)로 충분하다 const [n, goal, maxTurns, x0, a, c, m] = lines[g].trim().split(" ").map(Number); let x: number = x0; const scores: number[] = new Array<number>(n).fill(0); let winner = 0, turns = 0, rolls = 0, player = 0; while (turns < maxTurns && winner === 0) { turns++; let turnSum = 0, count = 0, face: number; do { // 첫 굴림은 언제나 한다 x = (a * x + c) % m; face = (x % 6) + 1; rolls++; count++; turnSum += face; } while (face === 6 && count < 3); if (face === 6) turnSum = 0; // 세 번 모두 6 scores[player] += turnSum; if (scores[player] >= goal) winner = player + 1; player = (player + 1) % n; } out.push(`${winner} ${turns} ${rolls}`, scores.join(" "));}console.log(out.join("\n"));
JavaMain.java · 36 行
import java.io.BufferedReader;import java.io.InputStreamReader;public class Main { public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int t = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int g = 0; g < t; g++) { String[] p = in.readLine().trim().split(" "); int n = Integer.parseInt(p[0]), goal = Integer.parseInt(p[1]), maxTurns = Integer.parseInt(p[2]); long x = Long.parseLong(p[3]), a = Long.parseLong(p[4]), c = Long.parseLong(p[5]), m = Long.parseLong(p[6]); // a * x는 int를 넘친다 int[] scores = new int[n]; int winner = 0, turns = 0, rolls = 0, player = 0; while (turns < maxTurns && winner == 0) { turns++; int turnSum = 0, count = 0, face; do { // 첫 굴림은 언제나 한다 x = (a * x + c) % m; face = (int) (x % 6) + 1; rolls++; count++; turnSum += face; } while (face == 6 && count < 3); if (face == 6) turnSum = 0; // 세 번 모두 6 scores[player] += turnSum; if (scores[player] >= goal) winner = player + 1; player = (player + 1) % n; } out.append(winner).append(' ').append(turns).append(' ').append(rolls).append('\n'); for (int i = 0; i < n; i++) out.append(i > 0 ? " " : "").append(scores[i]); out.append('\n'); } System.out.print(out); }}
C#Main.cs · 39 行
using System;using System.Text;class Program{ static void Main() { int t = int.Parse(Console.ReadLine()!.Trim()); var sb = new StringBuilder(); for (int g = 0; g < t; g++) { string[] p = Console.ReadLine()!.Trim().Split(' '); int n = int.Parse(p[0]), goal = int.Parse(p[1]), maxTurns = int.Parse(p[2]); long x = long.Parse(p[3]), a = long.Parse(p[4]), c = long.Parse(p[5]), m = long.Parse(p[6]); // a * x는 int를 넘친다 int[] scores = new int[n]; int winner = 0, turns = 0, rolls = 0, player = 0; while (turns < maxTurns && winner == 0) { turns++; int turnSum = 0, count = 0, face; do // 첫 굴림은 언제나 한다 { x = (a * x + c) % m; face = (int)(x % 6) + 1; rolls++; count++; turnSum += face; } while (face == 6 && count < 3); if (face == 6) turnSum = 0; // 세 번 모두 6 scores[player] += turnSum; if (scores[player] >= goal) winner = player + 1; player = (player + 1) % n; } sb.Append($"{winner} {turns} {rolls}\n"); sb.Append(string.Join(" ", scores)).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 33 行
#include <iostream>#include <vector>int main() { std::ios::sync_with_stdio(false); int t; std::cin >> t; while (t--) { int n, goal, maxTurns; long long x, a, c, m; // a * x는 10^12까지 커져서 int로는 넘친다 std::cin >> n >> goal >> maxTurns >> x >> a >> c >> m; std::vector<int> scores(n, 0); int winner = 0, turns = 0, rolls = 0, player = 0; while (turns < maxTurns && winner == 0) { turns++; int turnSum = 0, count = 0, face; do { // 첫 굴림은 언제나 한다 x = (a * x + c) % m; face = static_cast<int>(x % 6) + 1; rolls++; count++; turnSum += face; } while (face == 6 && count < 3); if (face == 6) turnSum = 0; // 세 번 모두 6 scores[player] += turnSum; if (scores[player] >= goal) winner = player + 1; player = (player + 1) % n; } std::cout << winner << ' ' << turns << ' ' << rolls << '\n'; for (int i = 0; i < n; i++) std::cout << (i ? " " : "") << scores[i]; std::cout << '\n'; }}
Cmain.c · 32 行
#include <stdio.h>int main(void) { int t; scanf("%d", &t); while (t--) { int n, goal, maxTurns; long long x, a, c, m; /* a * x는 10^12까지 커져서 int(약 21억)로는 넘친다 */ scanf("%d %d %d %lld %lld %lld %lld", &n, &goal, &maxTurns, &x, &a, &c, &m); int scores[8] = {0}; int winner = 0, turns = 0, rolls = 0, player = 0; while (turns < maxTurns && winner == 0) { turns++; int turnSum = 0, count = 0, face; do { /* 첫 굴림은 언제나 한다 */ x = (a * x + c) % m; face = (int)(x % 6) + 1; rolls++; count++; turnSum += face; } while (face == 6 && count < 3); if (face == 6) turnSum = 0; /* 세 번 모두 6 */ scores[player] += turnSum; if (scores[player] >= goal) winner = player + 1; player = (player + 1) % n; } printf("%d %d %d\n", winner, turns, rolls); for (int i = 0; i < n; i++) printf(i ? " %d" : "%d", scores[i]); putchar('\n'); } return 0;}
Craykonmain.cray · 49 行
t = コンソール.行読み().数に();繰り返す (g = 0; g < t; g++){ p = コンソール.行読み().空白除去().分ける(); n = p[0].数に(); 목표 = p[1].数に(); 최대차례 = p[2].数に(); x = p[3].数に(); a = p[4].数に(); c = p[5].数に(); m = p[6].数に(); 점수 = 新リスト(n, 0); 이긴사람 = 0; 차례수 = 0; 굴린수 = 0; 사람 = 0; 間 (차례수 < 최대차례 && 이긴사람 == 0) { 차례수++; 합 = 0; 번 = 0; 눈 = 0; // 크레이콘에는 do-while이 없다: 동안 (참)으로 들어가 끝에서 멈출지 묻는다(첫 굴림은 언제나 한다) 間 (真) { x = (a * x + c) % m; // 10^12까지라 정확하다 눈 = x % 6 + 1; 굴린수++; 번++; 합 += 눈; もし (!(눈 == 6 && 번 < 3)) { 抜ける; } } もし (눈 == 6) { 합 = 0; } 점수[사람] += 합; もし (점수[사람] >= 목표) { 이긴사람 = 사람 + 1; } 사람 = (사람 + 1) % n; } コンソール.書く(이긴사람 + " " + 차례수 + " " + 굴린수); コンソール.書く(점수.つなぐ(" "));}