Description
狼人游戏是一款深受大众欢迎的桌游。Ly作为初学者,自然也迷上这款刺激与智商并存的游戏。
可是有一件很忧伤的事,大家都知道狼人的角色牌分为狼人和非狼人,然后Ly经常玩一个晚上都抽不到狼人的角色。
为了抽到心爱的狼人,Ly开始观察主持人洗牌和发牌的规律。假设现在有n个人(分别编号1~n)玩游戏,也就是有n张牌,则主持人每一轮进行以下操作:
1.将手中的n张牌自顶到底编号1~n,并将它们从左到右放在反面放在桌面上;
2.记当前桌面剩下的牌里面,编号最小为m;
3.依此取编号为m,m+X,m+2*X….m+c*X的牌,直到m+c*X>n,每次取到的牌放到手牌的顶部;
4.如果桌面上还有牌,重复步骤2、3;否则洗牌完成,主持人重新将手牌自顶到底编号1~n;
5.游戏开始,主持人将第i张牌,发给编号为i的人;
6.游戏结束,主持人按游戏者编号回收角色牌,也就是第i个人的牌,放在第i位。
现在Ly知道自己的编号是k,还有就是在开局前,偷偷地把牌的初始状态记了下来,也就是说第一轮开始前第i张牌是不是狼人,Ly是知道的。游戏第一轮开始前主持人不洗牌。
由于大家今晚非常兴奋,打算玩通宵,你可以当作游戏进行了无数轮。Ly想知道他今晚有没有可能抽到狼人。但Ly正陶醉于游戏中,聪明的13级大神们,你可以帮Ly推测一下吗?O(∩_∩)O~
输入格式
第一行一个整数T(T<=20),表示测试数据的组数。
每组数据有两行。
第一行3个正整数n,X,k. n,X,k的含义如题目所述。
第二行一个长度为n的字符串,只由0和1组成。第i个字符代表初始状态下第i张牌的角色是不是狼人,1代表是,0代表不是。
数据范围:
3<=n<=1000
1<=k<=n
1<=X<=1000007
输出格式
每组数据输出一行。
如果Ly可以抽到狼人角色,输出”haha”;否则输出”hehe”。
输入样例
2
6 2 3
000010
6 2 1
000010
输出样例
haha
hehe
提示
1.在样例1中,第二轮开始前主持人洗牌后,角色牌的状况是000100;第三轮开始前主持人洗牌后的,角色牌的状况为010000;第四轮开始前主持人洗牌后,角色牌的状况为001000;于是坐在第3位
的Ly将在第四轮抽到狼人。
2.狼人角色牌的数量可以有多个。
3.此题用整体法和隔离法均可解,请认真思考分析。
解题思路
建立记录数组
record[ i ] = t
编号为 i 的牌下一轮游戏的编号为 t
则有:
t2 = record[ t ]
t3 = record[ t2 ]
t4 = record[ t3 ]
…
判断 tk == k || tk = i (即是否某一次游戏时编号等于k,或者回到初始编号)
#include<stdio.h>
int main()
{
int t, n, x, k, total, index, flag, temp, temp2;
int num[1002], record[1002], man[1002];
char ch;
scanf("%d", &t);
while(t --)
{
scanf("%d %d %d", &n, &x, &k);
total = n;
flag = 0;
scanf("%c", &ch);
for(int i = 1; i <= n; i ++)
{
scanf("%c", &ch);
man[i] = ch == '0' ? 0 : 1;
}
for(int i = 1; i <= n; i ++)
num[i] = i;
// 按照游戏规则建立记录数组
while(total >= 1)
{
// 从剩下的牌中找到编号最小的
for(index = 1; index <= n; index ++)
if(num[index] != -1)
break;
while(index <= n)
{
// 按照游戏规则:越早抽中的牌下次游戏时编号越大
record[num[index]] = total;
num[index] = -1;
total --;
index += x;
}
}
for(int i = 1; i <= n; i ++)
{
// 如果编号为 i 的牌是狼人牌
if(man[i] == 1)
{
temp = temp2 = i;
while(record[temp] != k && record[temp] != temp2)
temp = record[temp];
flag = record[temp] == k ? 1 : 0;
}
if(flag)
break;
}
printf("%s\n", flag == 1 ? "haha" : "hehe");
}
return 0;
}