Ultraviolet A 1558-Number Game
Question Link
Question: A number within 20. You can select a number at a time, then its multiples, and the number of multiples of other selected numbers cannot be selected again, no one can choose the number and lose. Ask the winning method.
Idea: Use DP memory to solve the problem. To output the solution, you can enumerate the first step. During the state transition process, select a number and write the corresponding changes as a function, then there is an ordinary game problem. After winning, the game will be defeated, and then the game will be defeated.
Code:
#include <stdio.h>#include <string.h>const int N = 1050005;int t, n, w, start, dp[N], ans[25], an;int getnext(int state, int x) {for (int i = x; i <= 20; i += x) if (state&(1<<(i - 2))) state ^= (1<<(i - 2));for (int i = 2; i <= 20; i++) {if (state&(1<<(i - 2))) {for (int j = x; i - j >= 2; j += x) {if (!(state&(1<<(i - j - 2)))) {state ^= (1<<(i - 2)); break;} } } } return state;}int dfs(int state) {if (dp[state] != -1) return dp[state];if (state == 0) return dp[state] = 0;for (int i = 2; i <= 20; i++) {if (state&(1<<(i - 2))) {if (dfs(getnext(state, i)) == 0)return dp[state] = 1; } } return dp[state] = 0;}int main() {int cas = 0;scanf("%d", &t);memset(dp, -1, sizeof(dp));while (t--) {start = 0; an = 0;scanf("%d", &n);for (int i = 0; i < n; i++) {scanf("%d", &w);start |= (1<<(w - 2)); } for (int i = 2; i <= 20; i++) { if (start&(1<<(i - 2))) { if (dfs(getnext(start, i)) == 0) ans[an++] = i; } } printf("Scenario #%d:\n", ++cas); if (an) { printf("The winning moves are:"); for (int i = 0; i < an; i++) printf(" %d", ans[i]); printf(".\n"); } else printf("There is no winning move.\n"); printf("\n"); }return 0;}
Ultraviolet A 1558-Number Game (game DP)