import sysdef main(): data = sys.stdin.read().split() k, q = int(data[0]), int(data[1]) asks = [int(x) for x in data[2:2 + q]] top = max(asks) # win[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가 win = [[False] * (k + 1) for _ in range(top + 1)] for r in range(1, top + 1): # good: 가져가면 상대가 지는 자리로 가는 개수들(제한은 아직 따지지 않음) good = [t for t in range(1, min(k, r) + 1) if not win[r - t][t]] row = win[r] for f in range(k + 1): row[f] = len(good) >= 2 or (len(good) == 1 and good[0] != f) out = [] for n in asks: first = [t for t in range(1, min(k, n) + 1) if not win[n - t][t]] out.append(" ".join(map(str, first)) if first else "0") print("\n".join(out))main()
JavaScriptmain.js · 31 行
const data = require("fs").readFileSync(0, "utf8").split(/\s+/).filter(Boolean).map(Number);const k = data[0], q = data[1];const asks = data.slice(2, 2 + q);const top = Math.max(...asks);// win[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가// fill(배열)은 같은 배열 하나를 모든 줄에 넣으므로, 줄마다 새로 만든다const win = Array.from({ length: top + 1 }, () => new Array(k + 1).fill(false));for (let r = 1; r <= top; r++) { // 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 let count = 0, only = 0; for (let t = 1; t <= k && t <= r; t++) { if (!win[r - t][t]) { count++; only = t; } } for (let f = 0; f <= k; f++) { win[r][f] = count >= 2 || (count === 1 && only !== f); }}const out = [];for (const n of asks) { const first = []; for (let t = 1; t <= k && t <= n; t++) { if (!win[n - t][t]) first.push(t); } out.push(first.length > 0 ? first.join(" ") : "0");}console.log(out.join("\n"));
TypeScriptmain.ts · 31 行
const data = require("fs").readFileSync(0, "utf8").split(/\s+/).filter(Boolean).map(Number);const k = data[0], q = data[1];const asks = data.slice(2, 2 + q);const top = Math.max(...asks);// win[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가// fill(배열)은 같은 배열 하나를 모든 줄에 넣으므로, 줄마다 새로 만든다const win: boolean[][] = Array.from({ length: top + 1 }, () => new Array(k + 1).fill(false));for (let r = 1; r <= top; r++) { // 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 let count = 0, only = 0; for (let t = 1; t <= k && t <= r; t++) { if (!win[r - t][t]) { count++; only = t; } } for (let f = 0; f <= k; f++) { win[r][f] = count >= 2 || (count === 1 && only !== f); }}const out: string[] = [];for (const n of asks) { const first: number[] = []; for (let t = 1; t <= k && t <= n; t++) { if (!win[n - t][t]) first.push(t); } out.push(first.length > 0 ? first.join(" ") : "0");}console.log(out.join("\n"));
JavaMain.java · 40 行
import java.util.*;public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int k = in.nextInt(), q = in.nextInt(); int[] asks = new int[q]; int top = 0; for (int i = 0; i < q; i++) { asks[i] = in.nextInt(); top = Math.max(top, asks[i]); } // win[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가 boolean[][] win = new boolean[top + 1][k + 1]; // 모두 false로 시작한다 for (int r = 1; r <= top; r++) { // 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 int count = 0, only = 0; for (int t = 1; t <= k && t <= r; t++) { if (!win[r - t][t]) { count++; only = t; } } for (int f = 0; f <= k; f++) { win[r][f] = count >= 2 || (count == 1 && only != f); } } StringBuilder out = new StringBuilder(); for (int n : asks) { StringJoiner first = new StringJoiner(" "); for (int t = 1; t <= k && t <= n; t++) { if (!win[n - t][t]) first.add(String.valueOf(t)); } out.append(first.length() > 0 ? first.toString() : "0").append('\n'); } System.out.print(out); }}
C#Main.cs · 51 行
using System;using System.Collections.Generic;using System.Text;class Program{ static void Main() { string[] data = Console.In.ReadToEnd().Split((char[])null, StringSplitOptions.RemoveEmptyEntries); int k = int.Parse(data[0]), q = int.Parse(data[1]); var asks = new int[q]; int top = 0; for (int i = 0; i < q; i++) { asks[i] = int.Parse(data[2 + i]); top = Math.Max(top, asks[i]); } // win[r, f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가 var win = new bool[top + 1, k + 1]; // 네모난 2차원 배열, 모두 false로 시작한다 for (int r = 1; r <= top; r++) { // 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 int count = 0, only = 0; for (int t = 1; t <= k && t <= r; t++) { if (!win[r - t, t]) { count++; only = t; } } for (int f = 0; f <= k; f++) { win[r, f] = count >= 2 || (count == 1 && only != f); } } var output = new StringBuilder(); foreach (int n in asks) { var first = new List<int>(); for (int t = 1; t <= k && t <= n; t++) { if (!win[n - t, t]) first.Add(t); } output.Append(first.Count > 0 ? string.Join(" ", first) : "0").Append('\n'); } Console.Write(output); }}
C++main.cpp · 44 行
#include <algorithm>#include <iostream>#include <vector>using namespace std;int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int k, q; cin >> k >> q; vector<int> asks(q); for (int &n : asks) cin >> n; int top = *max_element(asks.begin(), asks.end()); // win[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가 vector<vector<char>> win(top + 1, vector<char>(k + 1, 0)); // 줄마다 따로 복사된다 for (int r = 1; r <= top; r++) { // 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 int count = 0, only = 0; for (int t = 1; t <= k && t <= r; t++) { if (!win[r - t][t]) { count++; only = t; } } for (int f = 0; f <= k; f++) { win[r][f] = count >= 2 || (count == 1 && only != f); } } for (int n : asks) { bool printed = false; for (int t = 1; t <= k && t <= n; t++) { if (!win[n - t][t]) { if (printed) cout << ' '; cout << t; printed = true; } } if (!printed) cout << 0; cout << '\n'; } return 0;}
Cmain.c · 47 行
#include <stdio.h>#include <stdlib.h>#define MAX_N 9000#define MAX_K 10/* win[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가 */static char win[MAX_N + 1][MAX_K + 1]; /* 전역 배열은 모두 0으로 시작한다 */int main(void) { int k, q; if (scanf("%d %d", &k, &q) != 2) return 1; int *asks = malloc(sizeof(int) * q); int top = 0; for (int i = 0; i < q; i++) { scanf("%d", &asks[i]); if (asks[i] > top) top = asks[i]; } for (int r = 1; r <= top; r++) { /* 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 */ int count = 0, only = 0; for (int t = 1; t <= k && t <= r; t++) { if (!win[r - t][t]) { count++; only = t; } } for (int f = 0; f <= k; f++) { win[r][f] = count >= 2 || (count == 1 && only != f); } } for (int i = 0; i < q; i++) { int n = asks[i], printed = 0; for (int t = 1; t <= k && t <= n; t++) { if (!win[n - t][t]) { printf(printed ? " %d" : "%d", t); printed = 1; } } if (!printed) printf("0"); printf("\n"); } free(asks); return 0;}
Craykonmain.cray · 52 行
첫줄 = コンソール.数読み();k = 첫줄[0];q = 첫줄[1];묻는수 = [];끝 = 0;繰り返す (i = 0; i < q; i++){ n = コンソール.行読み().数に(); 묻는수.追加(n); 끝 = 数学.大きい方(끝, n);}// 이김[r][f]: 구슬이 r개 남았고 f개는 가져갈 수 없을 때(f = 0이면 제한 없음), 지금 둘 사람이 이기는가이김 = 新リスト(끝 + 1, 新リスト(k + 1, 偽));繰り返す (r = 1; r <= 끝; r++){ // 가져가면 상대가 지는 자리로 가는 개수가 몇 가지인지, 한 가지뿐이면 그것이 무엇인지 가짓수 = 0; 하나뿐 = 0; 繰り返す (t = 1; t <= k && t <= r; t++) { もし (!이김[r - t][t]) { 가짓수 += 1; 하나뿐 = t; } } 繰り返す (f = 0; f <= k; f++) { 이김[r][f] = 가짓수 >= 2 || 가짓수 == 1 && 하나뿐 != f; }}それぞれ (n の中 묻는수){ 첫수 = []; 繰り返す (t = 1; t <= k && t <= n; t++) { もし (!이김[n - t][t]) { 첫수.追加(t); } } もし (첫수.個数 > 0) { コンソール.書く(첫수); } でなければ { コンソール.書く(0); }}