POJ-1143

发布时间 2023-04-28 16:58:18作者: towboat

 

给定一个序列,轮到谁,取出一个数k删除,并删除i*k(i=1,2,3,.....),

设k1为已经删除的数,同时删除k1*i+k*j,(i=1,2,3,.....;j同上 ),轮到谁没数删除时谁就输了。。

 

求先手取数 可以取那些数字 ,能保证获胜

 

#include<iostream>
#include <cstring>
#include <algorithm>
#include <iomanip>
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0);
using namespace std ;
const int N =(1<<20)+20;
 int f[N] ;
 int b[N]; 
 bool dfs(int s,int x){
 	s-=(1<<x) ;
 	for(int i=2;i+x<=20;i++)
 		if ( !((1<<i)&s) && (1<<(i+x))&s )
 			s-=(1<<(i+x));
 			
 	if(f[s]>0) return 1 ;
 	if(f[s]<0) return 0;
 	
 	for(int i=2;i<=20;i++)
 		if( (1<<i)&s&&!dfs(s,i)){
 			return f[s]=1 ;
 		}
 	
 	f[s]=-1 ;
 	return 0 ;
 }
 signed main(){
	int n,v,k,cnt=1,flag=0;
	while (cin>>n&&n){
		k=0;
		if (flag)
			cout<<endl;
		memset(f,0,sizeof f);
		f[0]=-1;
		int ans=0;
		for (int i=0;i<n;i++){
			cin>>v;
			ans+=(1<<v);
		}
		for (int i=2;i<=20;i++)
			if(((1<<i)&ans)&&!dfs(ans,i))
				b[k++]=i;
		sort(b,b+k);
		k=unique(b,b+k)-b;
		
		cout<<"Test Case #"<<cnt++<<endl;
		if (k)
		{
			cout<<"The winning moves are: "; 
			for (int i=0;i<k;i++)
				cout<<b[i] << ((i==k-1)?"\n":" ");
		}
		else 
			cout<<"There's no winning move."<<endl;
		flag=1;
	}
	return 0;
}