HDU4664 Triangulation sg函数

20 篇文章 0 订阅

题目链接:HDU4664

Triangulation

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 783    Accepted Submission(s): 312


Problem Description
There are n points in a plane, and they form a convex set. 

No, you are wrong. This is not a computational geometry problem. 

Carol and Dave are playing a game with this points. (Why not Alice and Bob? Well, perhaps they are bored. ) Starting from no edges, the two players play in turn by drawing one edge in each move. Carol plays first. An edge means a line segment connecting two different points. The edges they draw cannot have common points. 

To make this problem a bit easier for some of you, they are simutaneously playing on N planes. In each turn, the player select a plane and makes move in it. If a player cannot move in any of the planes, s/he loses. 

Given N and all n's, determine which player will win. 
 

Input
First line, number of test cases, T. 
Following are 2*T lines. For every two lines, the first line is N; the second line contains N numbers, n 1, ..., n N

Sum of all N <= 10 6
1<=n i<=10 9.
 

Output
T lines. If Carol wins the corresponding game, print 'Carol' (without quotes;) otherwise, print 'Dave' (without quotes.)
 

Sample Input
  
  
2 1 2 2 2 2
 

Sample Output
  
  
Carol Dave
 

题意:一堆平面,每个平面一堆点,2人轮流在平面上连线,要求只能在同一平面上连,并且不可以相交或构成三角形,问谁会赢。

按照要求构建sg函数即可,每次连线都不可以相交,所以每连一条线就相当于把平面一分为二为2个字问题,打表求sg函数即可。由于数据量比较大,所以找规律,发现后面是有循环节的,求循环节即可。

//
//  main.cpp
//  HDU4664
//
//  Created by teddywang on 2016/9/6.
//  Copyright © 2016年 teddywang. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int T,n;
int sg[250];

int mex(int x)
{
    if(sg[x]>=0) return sg[x];
    int vis[40];
    memset(vis,0,sizeof(vis));
    for(int i=0;i<x-1;i++)
    {
        sg[i]=mex(i);
        sg[x-i-2]=mex(x-i-2);
        vis[sg[i]^sg[x-i-2]]=1;
    }
    for(int i=0;;i++)
    {
        if(!vis[i])
            return i;
    }
}

void getsg()
{
    memset(sg, -1, sizeof(sg));
    sg[0]=0;
    sg[1]=0;
    sg[2]=1;
    sg[3]=1;
    for(int i=0;i<230;i++)
    {
        sg[i+4]=mex(i+4);
    }
}

int SG(int x)
{
    if(x<200) return sg[x];
    else{
        x%=34;
        return sg[x+4*34];
    }
}

int main()
{
    getsg();
    //for(int i=0;i<200;i++)
      //  cout<<sg[i]<<endl;
    cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int num;
            scanf("%d",&num);
            ans^=SG(num);
        }
        if(ans==0) printf("Dave\n");
        else printf("Carol\n");
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值