CF282D Yet Another Number Game 题解
upd on 2025.11.14 根据要求删除部分“嘎”语气词。
Introduction
好玩的博弈 DP 嘎。
首先第一眼看到这个题目,感觉不怎么好维护,因为有
但是你不觉得很奇怪吗?这样好像就不可做了嘎。
于是我们再读一次题面,很震惊地发现,题目保证了
但是由于不总是
When n is 1
分析一下嘎。
当
很容易发现,当
但是当
所以当
When n is 2
接着考虑有两个数字的情况嘎。
容易定义出状态
容易发现 bool 类型的数组。这样正好也节约了空间。
由于一旦有一个必胜策略,就不存在失败的情况了,所以我们可以考虑从必败情况转移到必胜情况。反过来等同于浪费时间,因为初始化的时候状态就是失败,没必要再额外转移了。
接下来考虑具体的转移嘎。
首先肯定要枚举 continue 掉就好了。
还得枚举
然后就要看看能不能支持了。首先看只处理
同理,满足
这样我们就处理完了选一个数改变的操作,但还有一个是全局改变。也不难,只要
那么 DP 的部分就结束了。输出的时候判断一下,如果
When n is 3
最后考虑有三个数字的情况嘎。
这是最复杂的一种情况,但是其实上它的本质和
定义
枚举
同样也要判断
接着是转移:如果
答案与
Accepted code
Submission 嘎。
仅供参考,不得抄袭嘎。
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define fr first
#define se second
#define pb push_back
using namespace std;
const int N = 305;
int n,a[5];bool f[N][N],dp[N][N][N];
int read(){
int su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
if(n==1){
if(a[1]>0)cout<<"BitLGM\n";
else cout<<"BitAryo\n";
}else if(n==2){
for(int x=0;x<=a[1];x++)
for(int y=0;y<=a[2];y++){
if(f[x][y])continue;
for(int p=1;p<=300;p++){
if(x+p<=a[1])f[x+p][y]=1;
if(y+p<=a[2])f[x][y+p]=1;
if(x+p<=a[1]&&y+p<=a[2])f[x+p][y+p]=1;
}
}
if(f[a[1]][a[2]])cout<<"BitLGM\n";
else cout<<"BitAryo\n";
}else{
for(int x=0;x<=a[1];x++)
for(int y=0;y<=a[2];y++)
for(int z=0;z<=a[3];z++){
if(dp[x][y][z])continue;
for(int p=1;p<=300;p++){
if(x+p<=a[1])dp[x+p][y][z]=1;
if(y+p<=a[2])dp[x][y+p][z]=1;
if(z+p<=a[3])dp[x][y][z+p]=1;
if(x+p<=a[1]&&y+p<=a[2]&&z+p<=a[3])dp[x+p][y+p][z+p]=1;
}
}
if(dp[a[1]][a[2]][a[3]])cout<<"BitLGM\n";
else cout<<"BitAryo\n";
}
return 0;
}
Summary
这就是整个题目的思维逻辑了,并不难想,也不难写。个人感觉唯一麻烦的点是要分类讨论,不过
顺带一提,我觉得这个题目没有蓝的难度,思维和码量都够不到,不知道之前的评分是怎么弄的,也许远古嘎?不知道,但是个人认为绿会合理一些嘎。
At last
第一期嘎嘎题解,写的不太好,还请各位谅解嘎。
在此,嘎嘎喵要郑重感谢各位读者仔细认真阅读到最后嘎。
如果本篇题解对你有帮助的话,还麻烦你点一个小小的赞,真是太感谢了嘎!