D Seek the Joker I
链接:https://ac.nowcoder.com/acm/contest/11746/D
来源:牛客网
题目描述
长达数日的春日祭终于告一段落,作为巫女的朝野芳乃在打扫完神社本决定好好享受一下久违的宁静。然而守护了神刀数百年的丛雨难耐寂寞,希望芳乃能陪她一起玩扑克消解愁闷。
芳乃并不擅长市井的游戏,所以总是输多赢少。而昨日被芳乃的神乐舞深深吸引,以致一早就前来建实神社希望能再睹芳华的你碰巧听见了此事。尽管不知道为什么美丽的巫女要自言自语地为玩扑克而苦恼,但你毅然决然地毛遂自荐,希望能为芳乃一解眉间愁。
芳乃告诉了你丛雨准备了n张扑克牌作为牌堆,每人每次至多从牌堆顶部抽k张牌,至少抽1张牌。牌堆底部的最后一张牌作为乌龟,抽中的将输掉这一轮比赛。芳乃想知道在你的帮助下,她和丛雨都采取积极策略时,她自己是否一定能获胜。作为被丛雨邀请的一方,每轮游戏都是芳乃先抽。
因为看不见丛雨而误认芳乃罹患精神分裂的你在不由感叹红颜薄命的同时,决定尽全力帮助芳乃完成她的委托。
声明:本题中的所有角色在剧情发生时均已超过18岁。
输入描述:
第一行包含一个整数T,表示共有T组测试数据。
每组测试数据共一行,包含两个正整数n和k,分别表示牌堆中有n张牌和每次抽取最多抽取k张。
数据保证T,n,k≤1000000。
输出描述:
对于每组测试数据给出一行结果。
如果芳乃必胜,则输出“yo xi no forever!”,
否则输出 ”ma la se mi no.1!“。
解题思路:
威佐夫博奕
整个游戏不能拿最后一张牌,拿了就输了,除了最后一张牌还有n-1张
每个人可以摸1到k张牌,后手摸可以保证先手和后手这一轮总共摸得牌数为 k + 1,因为先手只能摸1到k张,然后算一下n-1是否能被k+1整除,如果可以整除,则后手刚好摸完n-1张只剩下一张后手胜利,如果不能整除,则先手胜。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
if((n-1)%(k+1)==0){
printf("ma la se mi no.1!\n");
}
else{
printf("yo xi no forever!\n");
}
}
return 0;
}
E Seek the Joker II
链接:https://ac.nowcoder.com/acm/contest/11746/E
来源:牛客网
题目描述
长达数日的春日祭终于告一段落,作为巫女的朝野芳乃在打扫完神社本决定好好享受一下久违的宁静。然而守护了神刀数百年的丛雨难耐寂寞,希望芳乃能陪她一起玩扑克消解愁闷。
芳乃并不擅长市井的游戏,所以总是输多赢少。而昨日被芳乃的神乐舞深深吸引,以致一早就前来建实神社希望能再睹芳华的你碰巧听见了此事。尽管不知道为什么美丽的巫女要自言自语地为玩扑克而苦恼,但你毅然决然地毛遂自荐,希望能为芳乃一解眉间愁。
芳乃告诉了你丛雨准备了n张扑克牌作为牌堆,自牌顶向下数第x张牌作为乌龟,即“乌龟”的上方有x-1张牌,“乌龟”的下方有n-x张牌,抽中“乌龟”的将输掉这一轮比赛。每人每次可以同时在牌堆顶和牌堆底或者仅在牌堆顶或牌堆底其抽取任意张牌,至少抽1张牌。但若选择同时在牌堆顶和牌堆底抽牌,则抽牌数量需要相同。芳乃想知道在你的帮助下,她和丛雨都采取积极策略时,她自己是否一定能获胜。作为被丛雨邀请的一方,每轮游戏都是芳乃先抽。
因为看不见丛雨而误认芳乃罹患精神分裂的你在不由感叹红颜薄命的同时,决定尽全力帮助芳乃完成她的委托。
声明:本题中的所有角色在剧情发生时均已超过18岁。
输入描述:
第一行包含一个整数T,表示共有T组测试数据。
每组测试数据共一行,包含两个正整数n和x,分别表示牌堆中有n张牌和”乌龟“的位置。
数据保证,T≤1000000 和n,x≤3000000 ,。
输出描述:
对于每组测试数据给出一行结果。
如果芳乃必胜,则输出“yo xi no forever!”,
否则输出”ma la se mi no.1!“。
解题思路:
思路来自于 这个博主的博弈论之威佐夫博弈https://blog.csdn.net/qq_41311604/article/details/79980882
根据这个博主写的,这个题我们只要舍掉乌龟那张牌,看先手后手谁先摸完牌谁就胜利,判断是否满足这个式子即可 left == (int) ((right - left )*1.618) 满足的话就是后手胜利,不满足就是先手胜利。left 是较小的数,right 是较大的数
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
double r = (sqrt(5.0) + 1) / 2; //r = 0.618
int t;
cin>>t;
while(t--){
int n,x;
cin>>n>>x;
int left,right;
left = x-1; right = n-x;
if(left>right)
swap(left,right);
int temp = (right-left)*r;
if(temp==left){
cout<<"ma la se mi no.1!"<<endl;
}
else{
cout<<"yo xi no forever!"<<endl;
}
}
return 0;
}