社区讨论

状压DP20分不过 求调

P2575高手过招参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lzv15ehw
此快照首次捕获于
2024/08/15 16:40
2 年前
此快照最后确认于
2024/08/15 18:46
2 年前
查看原帖
首先我把这个游戏分成了由每一行构成的组合游戏
f[i]f[i] 是指该行状态为 ii 时的 SGSG 函数
f[i]=mex(f[j])f[i]=mex(f[j]) 其中 jj 是能从 ii 到达的状态
CPP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1000009;
ll T,a[409],f[(1<<20)+9],cnt=0;
ll LSB(ll x){return x&(-x);}
ll mex(){
	sort(a+1,a+cnt+1);
	bool ok=0;
	ll ans=0;
	if(!cnt) return 0;
	for(ll i=1;i<=cnt;++i){
		if(a[i]==ans) ++ans,ok=1;
		if(ans<a[i]) return ans; 
	}
	return ans;
}
ll change(ll x,ll i){//第i列往右边走
	for(ll k=i+1;k<20;++k)
		if(!(x&(1<<k))){
//			cout<<x<<":"<<(x^(1<<i)^(1<<k))<<"\n";
			return x^(1<<i)^(1<<k);
		}
	return 0;
}
int main(){//11111111111111111111
	for(ll i=(1<<20)-1;i>=1;--i){
//ll i=(1<<20)-1;
//		cout<<i<<" ";
		if(LSB(i+1)==i+1) f[i]=0;
		else{
			cnt=0;
			for(ll j=0;j<20;++j)//移动j位 
				if(i&(1<<j)){//单调队列
					ll x=change(i,j);
					if(x) a[++cnt]=f[x];
				}
			f[i]=mex();
		}
	}
//	for(ll i=(1<<20)-1;i>=1;--i) cout<<f[i]<<" ";
	cin>>T;
	while(T--){
		ll n,sum=0;
		cin>>n;
		for(ll i=1;i<=n;++i){
			ll m,z=0;
			cin>>m;
			for(ll j=1;j<=m;++j){
				ll x;
				cin>>x;
				z|=(1<<(x-1));
			}
			sum^=f[z];
		}
		cout<<(sum?"YES\n":"NO\n");
	}
	
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...