题目描述:
rqdmap and his little girlfriend are playing a game. There are n positive integers. These two people take turns, taking the numbers. In order to show his Gentlemanliness, rqdmap asked his little girlfriend to take the numbers fifirst.
Every time rqdmap’s little girlfriend can choose any number from the remaining numbers to take away (recorded as x), rqdmap needs to choose a number from the remaining numbers (recorded as y), and at least one of the following two conditions is met:
1. |x − y| ≤ 3, that is, the difffference between the absolute values of x and y cannot exceed 3.
2. x ≡ y (mod 3), that is, x and y modulo 3 are congruent.
If rqdmap cannot select a qualifified number from the remaining numbers, rqdmap’s little girlfriend wins, otherwise rqdmap wins. rqdmap and his little girlfriend are smart enough. Now that you have obtained these numbers before the game starts, please judge who will win the game in the end.
中文翻译:
Rqdmap和他的小女友在玩游戏。有n个正整数。这两个人轮流数。为了显示他的绅士风度,rqdmap让他的小女朋友先拿号码。
每次rqdmap的小女友可以从剩余的数字中选择任意一个数字带走(记录为x), rqdmap需要从剩余的数字中选择一个数字(记录为y),并且至少满足以下两个条件中的一个:
1. |x−y|≤3,即x与y的绝对值之差不能超过3。
2. X≡y(取3模),即X与y取3模相等。
如果rqdmap不能从剩余的号码中选择一个合格的号码,rqdmap的小女友获胜,否则rqdmap获胜。Rqdmap和他的小女友够聪明的。既然你在比赛开始前已经得到了这些数字,请判断谁将最终赢得比赛。
题目思路:
1、首先n如果为奇数,那男生必输;
2、如果n为偶数,那在考虑{首先把数分为三堆,A(%3==0),B(%3==1),C(%3==2)}
2.1.如果三堆个数分别为偶数,则男生赢;男生的思路来说:我取是让堆里始终为偶数;
2.2如果三堆里面个数是(奇,奇,偶);
2.2.1,从奇数堆里拿一个,从偶数里拿一个;如果取成功了,男生就可以赢得胜利
2.2.2,如果上面没取成功,则从两个奇数堆里取两个数;如果取成功了,男生就可以胜利
2.2.3,如果以上都没成功,则女生赢了
题目代码:(代码是参照:先相信,再想信)
#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
using namespace std;
int a[1000009];
void solve()
{
int n;
cin>>n;
vector<int>p[3];
map<int,int>mp;
int a0=0,a1=0,a2=0;//分了三堆,计数
for(int i=1; i<=n; i++)
{
cin>>a[i];
mp[a[i]]++;
p[a[i]%3].push_back(a[i]);
if(a[i]%3==0) a0++;
else if(a[i]%3==1) a1++;
else a2++;
}
int flag=0;
if(a0%2==0&&a1%2==0&&a2%2==0)
{
cout <<"rqd"<<endl;
return ;
}
if(n%2==1)
{
cout <<"His little girlfriend"<<endl;
return ;
}
if(n%2==0)
{
int x=0;
while(p[x].size()%2==1) x++;
int l=-1,r=-1;
for(int i=0; i<p[x].size(); i++)
{
if(mp.count(p[x][i]+1)||mp.count(p[x][i]-2))
{
l=i;
break;
}
}
for(int i=0; i<p[x].size(); i++)
{
if(i!=l&&(mp.count(p[x][i]+2)||mp.count(p[x][i]-1)))
{
r=i;
break;
}
}//这两循环是判断了一奇一偶的选择
if(l!=-1&&r!=-1) flag=1;
x=(x+1)%3;//取两奇数的情况
for(int i=0; i<p[x].size(); i++)
{
if(mp.count(p[x][i]+1)||mp.count(p[x][i]-2))
{
flag=1;
break;
}
}
if(flag==1) cout <<"rqd"<<endl;
else cout <<"His little girlfriend"<<endl;
}
}
signed main()
{
IOS;
int __=1;
cin>>__;
while(__--)
{
solve();
}
}
总结:
对于这类问题,可以用画思维导图,注意拆解的方法;然后很重点的是一定要多分类分堆;然后再每堆的思路需要理解一下,正难则反;