P3185 [HNOI2007] 分裂游戏

news/2025/2/7 18:44:42/文章来源:https://www.cnblogs.com/LG017/p/18703096

P3185 [HNOI2007] 分裂游戏

题目描述

聪聪和睿睿最近迷上了一款叫做分裂的游戏。

该游戏的规则是: 共有 \(n\) 个瓶子, 标号为 \(0, 1, \ldots, n-1\),第 \(i\) 个瓶子中装有 \(p_i\) 颗巧克力豆,两个人轮流取豆子,每一轮每人选择 \(3\) 个瓶子,标号为 \(i,j,k\), 并要保证 \(i \lt j, j \leq k\),且第 \(i\) 个瓶子中至少要有 \(1\) 颗巧克力豆,随后这个人从第 \(i\) 个瓶子中拿走一颗豆子并在 \(j,k\) 中各放入一粒豆子(\(j\) 可能等于 \(k\)) 。如果轮到某人而他无法按规则取豆子,那么他将输掉比赛。胜利者可以拿走所有的巧克力豆!

两人最后决定由聪聪先取豆子,为了能够得到最终的巧克力豆,聪聪自然希望赢得比赛。他思考了一下,发现在有的情况下,先拿的人一定有办法取胜,但是他不知道对于其他情况是否有必胜策略,更不知道第一步该如何取。他决定偷偷请教聪明的你,希望你能告诉他,在给定每个瓶子中的最初豆子数后是否能让自己得到所有巧克力豆,他还希望你告诉他第一步该如何取,并且为了必胜,第一步有多少种取法?

输入格式

输入文件第一行是一个整数 \(t\),表示测试数据的组数。

每组测试数据的第一行是瓶子的个数 \(n\),接下来的一行有 \(n\) 个由空格隔开的非负整数,表示每个瓶子中的豆子数。

输出格式

对于每组测试数据,输出包括两行,第一行为用一个空格两两隔开的三个整数,表示要想赢得游戏,第一步应该选取的 \(3\) 个瓶子的编号 \(i,j,k\),如果有多组符合要求的解,那么输出字典序最小的一组。如果无论如何都无法赢得游戏,那么输出用一个空格两两隔开的三个 \(-1\)

第二行表示要想确保赢得比赛,第一步有多少种不同的取法。

提示

\(1 \leq t \leq 10\)\(2 \leq n \leq 21\)\(0 \leq p_i \leq 10^4\)

Solution:

博弈论部分:

P:

MnZn 刚学博弈论 1ms ......

首先我们先来介绍一下博弈论这一坨东西:定义博弈状态:

基本知识:

定理 1:没有后继状态的状态是必败状态。
定理 2:一个状态是必胜状态当且仅当存在至少一个必败状态为它的后继状态。
定理 3:一个状态是必败状态当且仅当它的所有后继状态均为必胜状态。

—— oiwiki

然后我们以 Nim 游戏 为例来说一下 sg 函数:

首先我们要进行一个转化:我们假设两个互不相交状态A,B,只要满足:

  • 1:没有后继状态的状态是\(B\)
  • 2:一个状态是 \(A\) 当且仅当存在至少一个 \(B\) 为它的后继状态。
  • 3:一个状态是 \(B\) 当且仅当它的所有后继状态均为 \(A\)

那么就可以说 \(A\) 是该游戏的必胜态,\(B\) 是该游戏的必败态

然后我们定义:

\(sg(x)=mex\) { \(sg(y) \ | \ y \in son(x)\) }

定义一个状态 \(S\) 的 sg 函数为该状态下所有点的 sg 函数的异或和。

然后我们将 $A=[sg(S) \ne 0] \ B= [sg(S) = 0] $ 带入 :

在 Nim 游戏中,我们将石子个数定为 \(sg\) 函数的值。
显然满足 :

  • 1:没有后继状态的状态是\(sg(S)=0\)

然后我们只需证明:

  • 2 :一个状态是 \(sg(S) \ne 0\) 当且仅当存在至少一个 \(sg(S) = 0\) 为它的后继状态。
  • 3:一个状态是 \(sg(S) = 0\) 当且仅当它的所有后继状态均为 \(sg(S) \ne 0\)

对于2,我们设 \(k=sg(S)\),假设他的二进制最高位为 \(d\) ,说明在这个状态下有奇数个数的二进制最高位为 \(d\),那么我们从中选一个数,将他的 \(d\) 位改成 0,然后将其他位改成去掉这个数之后剩下数的异或和

对于 3:很显然随便改一个数字就变成0了。

本题思路:

我们首先我们发现先手的操作是可以被后手仿照的,所以我们只关心豆子的奇偶性,然后我们\(O(n^3)\) 预处理构造出 sg 函数,对于每个询问构造初始状态然后再 \(O(n^3)\) 计数就好了。

Code:

#include<bits/stdc++.h>
const int N=21;
using namespace std;
int sg[N+5],vis[N<<2],a[N+5];
struct ANS{int i,j,k,cnt;
}ans;
int n;
void get_sg()
{sg[1]=0;for(int i=2;i<=N;i++){for(int j=1;j<=i;j++){for(int k=j;k<i;k++){vis[sg[j]^sg[k]]=i;for(sg[i]=0;vis[sg[i]]==i;sg[i]++);}}}
}
void solve(int x)
{ans={-1,-1,-1,0};for(int i=n;i;i--)for(int j=i-1;j;j--)for(int k=j;k;k--){if(!(x^sg[i]^sg[j]^sg[k])){if(!ans.cnt)ans=(ANS){n-i,n-j,n-k,1};反转else ans.cnt++;}}printf("%d %d %d\n%d\n",ans.i,ans.j,ans.k,ans.cnt);
}
void work()
{cin>>n;int x=0;for(int i=n;i;i--)cin>>a[i];//注意,这里将数组反转了。for(int i=1;i<=n;i++)if(a[i]&1)x^=sg[i];solve(x);
}
int main()
{//freopen("P3185.in","r",stdin);freopen("P3185.out","w",stdout);ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);get_sg();int T;cin>>T;while(T--)work();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/880162.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型时代的软件进化论:恐龙式软件 vs. 猴群式软件

春节期间,IT圈内两件大事持续发酵,一件是中国大模型DeepSeek R1的开源震动全球AI界,让中国科技界扬眉吐气,廉价大模型走入千家万户;另一件是SAP被客户居然之家告上法庭,要求索赔590万开发费用和1700万软件费用,最终法院判SAP退还350万研发费用。这两件事的背后,实际上映…

xtrabackup 命令备份

Percona XtraBackup 安装下载地址: https://downloads.percona.com/downloads/Percona-XtraBackup-8.0/Percona-XtraBackup-8.0.35-32/binary/redhat/8/x86_64/percona-xtrabackup-80-8.0.35-32.1.el8.x86_64.rpm 官方YUM安装说明: Percona 版本和 YUM - Percona XtraBackup在…

React—03—类组件中事件处理函数的this绑定、事件处理函数的传参;jsx的条件判断渲染;jsx的循环渲染

零、如何给html元素加事件监听 1.原生方式:通过querySelector()方法,捕捉到元素,比如说button元素,然后通过btn.onclick = () =>{}或者通过btn.addEventListensers(click, ()=>{})的方式 2.vue的方式,在元素上使用v-on指令,比如@click 3.react方式,在元素上使用事…

巧用通义灵码,提升前端研发效率

本次分享,主题是利用通义灵码提升前端研发效率。分享内容主要包括以下几部分:首先,我将从前端开发的角度介绍对通义灵码的基本认识;其次,我将展示通义灵码在日常研发中的应用案例;然后,我将通过实例说明,良好的设计能够显著提升通义灵码的效果。在第四个部分,我将介绍…

linux服务器离线安装ollama

一、前言 公司服务器在线安装ollama总是超时连接不上,想着本质就是个安装包,离线安装也可以。固有了这样的一篇博客记录一下。 二、流程 1、查看服务器cpu架构 执行指令 lscpu# x86_64 CPU选择下载ollama-linux-amd64 # aarch64|arm64 CPU选择下载ollama-linux-arm642、下载对…

数字孪生与智慧工厂完美融合,推动智能制造新时代

随着工业4.0和智能制造的浪潮席卷全球,数字孪生技术成为了现代工业发展的重要驱动力。数字孪生,作为一种能够在虚拟环境中精确再现物理实体的技术,通过实时数据的流动和反馈,创建了一个高度仿真的“数字模型”,而这一模型不仅仅停留在静态的模拟阶段,而是与现实世界保持实…

【字符串处理之sscanf函数】读入HH:MM:SS:NN型时间;读入日期

读取时间 HH:MM:SS:NN型 函数 //转为毫秒表示,方便比大小 int get(string time) {int h, m, s, ms;//从字符串内读数据sscanf(time.c_str(), "%d:%d:%d.%d", &h, &m, &s, &ms);return h * 3600000 + m * 60000 + s * 1000 + ms; }样例1 输入 3 23:4…

【字符串处理sscanf】读入HH:MM:SS:NN型时间

读取时间 HH:MM:SS:NN型 函数 //转为毫秒表示,方便比大小 int get(string time) {int h, m, s, ms;//从字符串内读数据sscanf(time.c_str(), "%d:%d:%d.%d", &h, &m, &s, &ms);return h * 3600000 + m * 60000 + s * 1000 + ms; }样例1 输入 3 23:4…

如何阅读一本书

明确自己阅读的目的扩充知识:期望扩充哪方面的知识呢 研究他人的方法论? 深挖某些知识点?当前看的内容是否合适? 应用方法论SQ3R 阅读法Survey (预览): 快速浏览标题、目录、摘要等,了解文章或书籍的大意。 Question (提问): 对内容提出问题,带着问题阅读能提高理解力。 …

【转载】在windows下vscode终端里无法运行脚本解决方案

windows下使用vscode中的终端运行脚本出现以下的问题解决方案: 以管理员身份打开vscode,任意打开一个终端 在终端中输入get-ExecutionPolicy,若返回Restricted,说明现在是vscode是被禁止运行脚本 输入set-ExecutionPolicy RemoteSigned 这段命令 再看看现在的状态,输入 ge…

(转!)A卡玩转Stable Diffusion

转:https://www.fujieace.com/ai/amd-stable-diffusion.html今天,一位网友通过查看“设备管理器”,发现他的显卡是“AMD Radeon RX 580 2048SP”。因此,Stable Diffusion用显卡却怎么也跑不起来?一生成图片就报错误“rocBLAS error: Could not initialize Tensile library…

心脏支架 All In One

心脏支架 All In One心脏支架 All In One 冠状动脉成形术和支架植入术 冠状动脉成形术和支架置入术又称为经皮冠状动脉介入治疗。心脏支架副作用https://www.mayoclinic.org/zh-hans/tests-procedures/coronary-angioplasty/about/pac-20384761 demos(🐞 反爬虫测试!打击盗版…