2021牛客暑期多校训练营1 Alice and Bob(结论,sg打表|优化)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营1 Alice and Bob(结论,sg打表|优化)相关的知识,希望对你有一定的参考价值。
A l i c e Alice Alice和 B o b Bob Bob做游戏, A l i c e Alice Alice先手.
每次每个人可以从其中一堆拿走 k ( k > 0 ) k(k>0) k(k>0)个石子,同时从另一堆拿走 s ∗ k ( s > = 0 ) s*k(s>=0) s∗k(s>=0)个石子
谁不能操作谁就输了,问胜负情况.
容易想到定义 f [ i ] [ j ] f[i][j] f[i][j]表示两堆式子分别剩下 i , j i,j i,j个的胜负情况
可以暴力枚举转移,复杂度为 O ( n 3 l o g ( n ) ) O(n^3log(n)) O(n3log(n))
然后发现
n
n
n不大可以暴力打表,比赛中也有人这么干了
不过 n n n大一点就没办法了
结论
当一堆石子个数为 i i i时,另一种石子只有一种情况能使后手必胜
证明
反证法,假设 ( i , p ) (i,p) (i,p)和 ( i , q ) (i,q) (i,q)都是后手必胜(其中 p > q p>q p>q)
设现在局面为 ( i , p ) , (i,p), (i,p),那么先手第一次从第二堆式子拿走 p − q p-q p−q个
局面变为 ( i , q ) (i,q) (i,q),这不就说明先手其实是必胜的吗?
所以状态 ( i , p ) (i,p) (i,p)是必胜态
于是,可以发现 f [ i ] [ j ] f[i][j] f[i][j]中后手必胜的情况最多只有 n n n种
于是可以把后手必胜的状态提取出来,能转移到这个状态的 f [ i ] [ j ] f[i][j] f[i][j]都是先手必胜
复杂度 O ( n 2 l o g ( n ) ) O(n^2log(n)) O(n2log(n))
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e3+10;
bool f[maxn][maxn];
vector<int>ans;
void init()
{
int z = 0, w = 0;
for(int i=0;i<=5000;i++)
for(int j=0;j<=5000;j++)
{
if( f[i][j] ) continue;//先手必胜跳过
for(int fi=1;i+fi<=5000;fi++)//从第一堆里面拿走fi个
for(int se=0;j+se<=5000;se+=fi)//从第二堆里面拿走se个
f[i+fi][j+se] = true;
for(int fi=1;j+fi<=5000;fi++)
for(int se=0;i+se<=5000;se+=fi)
f[i+se][j+fi] = true;
}
}
int main()
{
init();
int t; cin >> t;
while( t-- )
{
int n,m; cin >> n >> m;
if( f[n][m] ) cout << "Alice\\n";
else cout << "Bob\\n";
}
}
以上是关于2021牛客暑期多校训练营1 Alice and Bob(结论,sg打表|优化)的主要内容,如果未能解决你的问题,请参考以下文章