nyoj 913 取石子(十) (sg函数)

来源:互联网 发布:android5.0源码下载 编辑:程序博客网 时间:2024/06/03 20:53

取石子(十)
时间限制:1000 ms | 内存限制:65535 KB
难度:6

描述

不知不觉取石子已经到第十道了。地球上的石子也快要取完了!开个玩笑,当然还是有很多石子的,取石子的题目也是做不完的,今天又来了一道!有n堆石子,每一堆的规则如下:第一堆每次只能取2的幂次(即:1,2,4,8,16…);第二堆只能取菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量,斐波那契数即后面的数是前面两个数的和);第三堆可以取任意多个,最小1个,最多可以把这一堆石子取完;第四堆只能取1和偶数个(即:1,2,4,6,8,10...);第五堆只能取奇数个(即:1,3,5,7,9.....);好吧,这样下去太烦人了,六堆及其以后每堆最多取的数量为堆数编号,即第六堆只能取(1,2,3,4,5,6),第七堆只能取(1,2,3,4,5,6,7)....别看规则很多,但Yougth和Hrdv都是聪明人,现在由Yougth先取,比赛规定谁先取完所有石子既为胜者,输出胜者的名字。

输入
有多组测试数据,每组测试数据开始有一个n。
后面有n个数代表每一堆石子的数量,当n为0是表示输入结束。(所有数据小于1000)
输出
假如Yougth赢输出“Yougth”,Hrdv赢输出“Hrdv”。
样例输入

62 4 2 3 6 7 

样例输出

Hrdv

思路:我们通过算出每堆石子的sg函数值可以发现规律
1. sg函数值为1,2,0循环
2. 无规律
3. sg[a]=a
4. 无规律
5. sg函数值为1,0循环
6. sg[a]=amod(i+1),i为第i
所以说我们只需要打表求出第2堆和第4堆的sg函数值就可以了.

ac代码:

/* ***********************************************Author       : AnICoo1Created Time : 2016-07-26-20.45 TuesdayFile Name    : D:\MyCode\2016-7-26\1.cppLANGUAGE     : C++Copyright  2016 clh All Rights Reserved************************************************ */#include<stdio.h>#include<math.h>#include<string.h>#include<stack>#include<set>#include<map>#include<queue>#include<vector>#include<iostream>#include<algorithm>#define MAXN 1010000#define LL long long#define INF 0xfffffff#define mem(x) memset(x,0,sizeof(x))#define PI acos(-1)#define eps 1e-8using namespace std;//headint sg[5][1010];int v[1010],vis[1010];int f[1010];void getsg(int n,int x){    mem(v);    for(int i=1;i<1010;i++)    {        mem(vis);        for(int j=1;f[j]<=i&&j<n;j++)        {            //if(i==4)                //printf("%d\n",i-f[j]);            vis[sg[x][i-f[j]]]=1;        }        for(int j=0;j<=i;j++)        if(vis[j]==0)        {            sg[x][i]=j;            break;        }    }}void init(){    mem(sg);    int i,j,k;    f[1]=1;f[2]=2;k=f[1]+f[2];    for(i=3;k<=1000;i++)        f[i]=k,k=f[i]+f[i-1];    //printf("%d\n",i);    getsg(i,2);    f[1]=1;k=2;    for(i=2;k<=1000;i++)        f[i]=k,k+=2;    getsg(i,4);    //for(j=1;j<i;j++)       // printf("%d ",sg[2][j]);}int main(){    int n;init();    while(scanf("%d",&n)!=EOF)    {        int ans=0;        for(int i=1;i<=n;i++)        {            int a;cin>>a;            if(i==2||i==4)                ans^=sg[i][a];            else if(i==1)                ans^=(a%3);            else if(i==3)                ans^=a;            else if(i==5)                ans^=(a%2);            else if(i>=6)                ans^=(a%(i+1));        }        if(ans)            printf("Yougth\n");        else            printf("Hrdv\n");    }    return 0;}
0 0
原创粉丝点击