C. Card Game

Problem - C - Codeforces

题意是给你n张牌,序号是1到n,然后每一轮各出一张(不放回),直到没有更大的牌为止。每一轮先手交换,问你最后谁赢

博弈论一般先想决策,然后想必胜态或者必输态,然后开始继续考虑

这个题的决策是:

两堆牌,先手出最大的牌,后者出他那堆比出的这个牌大的最小的牌

知道了这个就好做了

为什么是这个决策呢:

先手必定是想让自己赢的,所以牌如果取小了,必输,所以取一张自己所拥有的最大的牌。然后后者想要不输,必须找一张更大的,但是不能用最大的,因为后面还有轮数要进行

所以这里思路来了:

把牌分成两堆,令f[i]是牌数先手必胜的方案数

先手必胜有两种状态:

①有此时最大的牌(i*2),此时先手必胜

②此时先手有(2*i-1)的牌,后手有(2*i)的牌,这个时候两个牌相互抵消。然后下一轮应该是后者轮了,这个时候应该是后者轮的先手输,才会保证本来的先手必胜

总的来说:本局的先手必胜态=本局的必胜+上一局的先手必胜,然后递推即可

下面看代码:

实现用组合数,只讲了思路

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define IOS ios::sync_with_stdio(false), cin.tie(0);
#include<iostream>
#include<map>
#include<set> 
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PAII;
const int N=2e6+10,M=5050,INF=1e18,mod=998244353;
int f[M],c[M][M]; 
int n;
void init()
{
    for (int i = 0; i < 200; i ++ )
        for (int j = 0; j <= i; j ++ )
            if (!j) c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
} 
signed main(){
    IOS;
    int T;
    //T=1;
    cin>>T;
    init();
	f[1]=1;
	for(int i=2;i<=30;i++)
		f[i]=(c[2*i-1][i-1] + (c[(i-1)*2][i-1] - f[i-1]-1)+mod)%mod;//递推:这一轮必胜态+上一轮的必胜态 
    while(T--)
    {
		cin>>n;
		n/=2;
		cout<<f[n]<<" "<<(c[n*2][n] - f[n] - 1+mod)%mod<<" "<<"1\n";//负数取模
    }
    return 0;
} 
/*

*/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <stdio.h> #include <stdlib.h> #define CARD_NUM 52 #define PLAYER_NUM 2 typedef struct Card { int number; char suit; } Card; void initializeDeck(Card deck[]) { int i, j, count = 0; for (i = 1; i <= 13; i++) { for (j = 0; j < 4; j++) { deck[count].number = i; switch (j) { case 0: deck[count].suit = 'S'; // Spade break; case 1: deck[count].suit = 'H'; // Heart break; case 2: deck[count].suit = 'D'; // Diamond break; case 3: deck[count].suit = 'C'; // Club break; } count++; } } } void shuffleDeck(Card deck[]) { int i, j; Card temp; for (i = 0; i < CARD_NUM; i++) { j = rand() % CARD_NUM; temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } void playGame(Card deck[]) { Card player1[CARD_NUM/2]; Card player2[CARD_NUM/2]; int currentPlayer = 1; // Player 1 starts the game int table[CARD_NUM]; int tableSize = 0; int i, j, k, found; // Distribute cards to players for (i = 0; i < CARD_NUM / 2; i++) { player1[i] = deck[i]; player2[i] = deck[i + CARD_NUM / 2]; } // Main game loop while (1) { if (currentPlayer == 1) { printf("Player 1's turn:\n"); printf("Player 1 plays: %d%c\n", player1[0].number, player1[0].suit); table[tableSize++] = player1[0].number; // Check if there are any cards to take from the table found = 0; for (i = 0; i < tableSize; i++) { if (table[i] == player1[0].number) { found = 1; break; } } if (found) { printf("Player 1 takes: "); for (j = i; j < tableSize; j++) { printf("%d%c ", table[j], player1[0].suit); } printf("\n"); // Remove cards from the table for (j = i; j < tableSize; j++) { for (k = j; k < tableSize - 1; k++) { table[k] = table[k + 1]; } tableSize--; } } // Remove card from player's hand for (i = 0; i < CARD_NUM / 2 - 1; i++) {
07-14

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值