进行若干局骰子游戏。 一局有 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 会掷第四次,漏掉清零会加上 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; } 控制台.输出(이긴사람 + " " + 차례수 + " " + 굴린수); 控制台.输出(점수.连接(" "));}