HDU - 1079 Calendar Game

题目:从1900,1,1到2001,11,4中给出一个日期,游戏者轮流操作,每个人可以选择移到下一个日期,或者选择到下一个月的相同日历日,当然这都是在合理的情况下进行操作,谁先到达2001,11,4谁胜,问是否先手必胜

思路:利用NP状态定理,直接预处理出来

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3fn
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
//0x3f3f3f3f

int mon[2][13]={
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}
};
int sg[105][13][35];
bool judge(int y){
    y+=1900;
    if(y%400==0) return 1;
    if(y%100!=0&&y%4==0) return 1;
    return 0;
}
void init_sg(){
    mm(sg,-1);
    sg[101][11][4]=0;//标记为P状态
    for(int i=5;i<=mon[0][11];i++) sg[101][11][i]=1;//标记为N状态
    for(int i=1;i<=mon[0][12];i++) sg[101][12][i]=1;//标记为N状态
    for(int y=101;y>=0;y--)
        for(int m=12;m>=1;m--){
            for(int d=mon[judge(y)][m];d>=1;d--){
                if(sg[y][m][d]!=-1) continue;
                int y1=y,m1=m+1,d1=d;
                int y2=y,m2=m,d2=d+1;
                if(m1>12){
                    m1=1;
                    y1++;
                }
                if(d2>mon[judge(y2)][m2]){
                    d2=1;
                    m2++;
                }
                if(m2>12){
                    m2=1;
                    y2++;
                }
                if(d1<=mon[judge(y1)][m1]){
                    if(sg[y1][m1][d1]==1&&sg[y2][m2][d2]==1)
                        sg[y][m][d]=0;
                    else
                        sg[y][m][d]=1;
                }
                else
                    sg[y][m][d]=!sg[y2][m2][d2];
            }
        }
}
int main(){

    int T,y,m,d;
    init_sg();
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&y,&m,&d);
        if(sg[y-1900][m][d]) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值