hdu 3980 Paint Chain

36 篇文章 0 订阅

题目链接:点这里

Problem Description

Aekdycoin and abcdxyzk are playing a game. They get a circle chain with some beads. Initially none of the beads is painted. They take turns to paint the chain. In Each turn one player must paint a unpainted beads. Whoever is unable to paint in his turn lose the game. Aekdycoin will take the first move.

Now, they thought this game is too simple, and they want to change some rules. In each turn one player must select a certain number of consecutive unpainted beads to paint. The other rules is The same as the original. Who will win under the rules ?You may assume that both of them are so clever.

Input

First line contains T, the number of test cases. Following T line contain 2 integer N, M, indicate the chain has N beads, and each turn one player must paint M consecutive beads. (1 <= N, M <= 1000)

Output

For each case, print "Case #idx: " first where idx is the case number start from 1, and the name of the winner.

Sample Input

2 
3 1 
4 2

Sample Output

Case #1: aekdycoin 
Case #2: abcdxyzk

【题意】

两个人玩游戏,开始的时候有n个没上色的东西围成一个环。然后两个人相互操作。每次选择一段连续的长度为m的没上色的东西给他上色。不能进行此操作的人算输。问你最后谁能胜利(假设两人均完美操作)。

【分析】

单局游戏。直接分析过程就行。首先,本来是环状的,第一个人涂色之后(如果可以的话),显然就是将环状直接弄成了链状。而且显然可以得到的是第一次涂色的位置是没有影响的。也就是说选择哪个地方都一样。所以第一次涂色的过程是固定的。后面的过程就不用考虑是否是链状还是环状了。直接当成链做就行了。剩下的过程就是博弈了。显然每个人操作之后的结果就是将一条链分解成了两条链,也就是说当前链的后继状态是由两条的状态决定的。这里直接简单的求一下nim和就行了。当然你会问如果从头开始取怎么办。显然还是会生成两条链啊,只不过有一条的长度是0罢了。然后剩下的就是求SG了。别忘了记忆化,不然会tle到怀疑人生(别问我经历了多少次)。

【代码】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<sstream>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS_1(a) memset(a,-1,sizeof(a))
#define MSinf(a) memset(a,0x3f,sizeof(a))
#define sin1(a) scanf("%d",&(a))
#define sin2(a,b) scanf("%d%d",&(a),&(b))
#define sll1(a) scanf("%lld",&(a))
#define sll2(a,b) scanf("%lld%lld",&(a),&(b))
#define sdo1(a) scanf("%lf",&(a))
#define sdo2(a,b) scanf("%lf%lf",&(a),&(b))
#define inf 0x3f3f3f3f
//#define lson i<<1,l,mid
//#define rson ((i<<1)|1),mid+1,r
#define uint unsigned int
typedef pair<int,int> PII;
#define A first
#define B second
#define pb push_back
#define MK make_pair
#define ll long long
template<typename T>
void read1(T &m) {
    T x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    m = x*f;
}
template<typename T>
void read2(T &a,T &b) {
    read1(a);
    read1(b);
}
template<typename T>
void read3(T &a,T &b,T &c) {
    read1(a);
    read1(b);
    read1(c);
}
template<typename T>
void out(T a) {
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
template<typename T>
void outn(T a) {
    if(a>9) out(a/10);
    putchar(a%10+'0');
    puts("");
}
using namespace std;
///------------------------------------------------------------------------------------
int sg[1005][1005];
int getsg(int len,int x)
{
    if(sg[len][x]!=-1) return sg[len][x];
    if(x>len) return 0;
    if(x==len) return 1;
    bool flag[1005];
    memset(flag,false,sizeof(flag));
    rep1(i,x,len)
    flag[getsg(i-x,x)^getsg(len-i,x)] = true;
    rep0(i,0,1005)
        if(!flag[i])
            return (sg[len][x]=i);
}
int main() {
//    freopen("in.txt","r",stdin);
    int T,a,b;
    read1(T);
    MS_1(sg);
    rep1(zzz,1,T)
    {
        printf("Case #%d: ",zzz);
        read2(a,b);
        if(b>a||getsg(a-b,b)) puts("abcdxyzk");
        else puts("aekdycoin");
    }
    return 0;
}

【续】

后来发现其实那个记忆化不是很好,因为开了个二维的,当时我想的是如果查询有重复的话可能比较省时间。后来压下了一维,发现时间反而小了。可能是数据比较水。不过题目里面确实没说数据组数是多少,可能是我想多了吧。

【代码2】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<sstream>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS_1(a) memset(a,-1,sizeof(a))
#define MSinf(a) memset(a,0x3f,sizeof(a))
#define sin1(a) scanf("%d",&(a))
#define sin2(a,b) scanf("%d%d",&(a),&(b))
#define sll1(a) scanf("%lld",&(a))
#define sll2(a,b) scanf("%lld%lld",&(a),&(b))
#define sdo1(a) scanf("%lf",&(a))
#define sdo2(a,b) scanf("%lf%lf",&(a),&(b))
#define inf 0x3f3f3f3f
//#define lson i<<1,l,mid
//#define rson ((i<<1)|1),mid+1,r
#define uint unsigned int
typedef pair<int,int> PII;
#define A first
#define B second
#define pb push_back
#define MK make_pair
#define ll long long
template<typename T>
void read1(T &m) {
    T x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    m = x*f;
}
template<typename T>
void read2(T &a,T &b) {
    read1(a);
    read1(b);
}
template<typename T>
void read3(T &a,T &b,T &c) {
    read1(a);
    read1(b);
    read1(c);
}
template<typename T>
void out(T a) {
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
template<typename T>
void outn(T a) {
    if(a>9) out(a/10);
    putchar(a%10+'0');
    puts("");
}
using namespace std;
///------------------------------------------------------------------------------------
int sg[1005];
int getsg(int len,int x)
{
    if(sg[len]!=-1) return sg[len];
    if(x>len) return 0;
    if(x==len) return 1;
    bool flag[1005];
    memset(flag,false,sizeof(flag));
    rep1(i,x,len)
    flag[getsg(i-x,x)^getsg(len-i,x)] = true;
    rep0(i,0,1005)
        if(!flag[i])
            return (sg[len]=i);
}
int main() {
//    freopen("in.txt","r",stdin);
    int T,a,b;
    read1(T);
    rep1(zzz,1,T)
    {
        printf("Case #%d: ",zzz);
        MS_1(sg);
        read2(a,b);
        if(b>a||getsg(a-b,b)) puts("abcdxyzk");
        else puts("aekdycoin");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zuhiul

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值