HDU 3980 Paint Chain

来源:互联网 发布:iapp轰炸机源码 编辑:程序博客网 时间:2024/05/17 07:04

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3980


题意:有一个含n个点的环,每次只能选择连续的m个点去涂色,两个人轮流去涂色,不能操作的人输。


思路:首先考虑到一个环,无论怎么先去涂m个点,都是一样的,会剩下n-m个点形成一条链。如果转化成链的话,这个问题模型就好做了,要么选择涂边上的m个点变成sg[i-m]这个状态,要么选择涂中间m个点,将链分成两条链,也就是分成两个单一游戏来进行就是转移到sg[j]^sg[i-m-j],所以我们先把链模型的sg函数打表出来,那么sg[n-m]就是先手取完后,后手面临的局面。


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <iostream>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <sstream>#include <queue>#include <utility>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))#define LL long long#define ULL unsigned long long#define inf 0x7fffffff#define mod 100000007const int maxn = 1009;int sg[maxn];int T,n,m;bool solve(){    bool temp[maxn*2];    if ( n < m ) return false;    if ( n == m ) return true;    Clean(sg,0);    sg[m] = 1;    rep(i,m+1,n)    {        Clean(temp,false);        temp[ sg[i-m] ] = true;        if ( i - m > 1 )        {            int k = i - m;            rep(j,1,k-1)                temp[ sg[j] ^ sg[k-j] ] = true;        }        int j = 0;        while( temp[j] ) j++;        sg[i] = j;    }    return sg[n-m]==0;}int main(){    cin>>T;    rep(kase,1,T)    {        scanf("%d%d",&n,&m);        printf("Case #%d: %s\n",kase,solve()?"aekdycoin":"abcdxyzk");    }    return 0;}


0 0
原创粉丝点击