주사위 놀이를 여러 판 한다.
한 판에는 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()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
한 차례가 '먼저 굴리고, 그다음 더 굴릴지 묻는' 모양이라 do-while이 꼭 맞아요. Java·C#·C·C++·JavaScript·TypeScript는 do { 굴리기 } while (face == 6 && count < 3);로 쓰고, do-while이 없는 Python은 while True: 안에서 굴린 뒤 끝에서 if not (...): break로, 크레이콘은 동안 (참) { … 만약 (!(…)) { 그만; } }으로 써요. 함정 넷: ① 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·크레이콘의 수는 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; } 콘솔.쓰기(이긴사람 + " " + 차례수 + " " + 굴린수); 콘솔.쓰기(점수.잇기(" "));}