题目描述

石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一 样,则不分胜 负。在《生活大爆炸》第二季第8集中出现了一种石头剪刀布的升级版游戏。
升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:
斯波克:《星际迷航》主角之一。
蜥蜴人:《星际迷航》中的反面角色。
这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。

现在,小 A和小 B尝试玩这种升级版的猜拳游戏。已知他们的出拳都是有周期性规律的,但周期长度不一定相等。例如:如果小A以“石头-布-石头-剪刀-蜥蜴人-斯波克”长度为 66 的周期出拳,那么他的出拳序列就是“石头-布-石头-剪刀-蜥蜴人-斯波克-石头-布-石头-剪刀-蜥蜴人-斯波克-…”,而如果小B以“剪刀-石头-布-斯波克-蜥蜴人”长度为 55 的周期出拳,那么他出拳的序列就是“剪刀-石头-布-斯波克-蜥蜴人-剪刀-石头-布-斯波克-蜥蜴人-…”
已知小 A和小 B 一共进行 $N $次猜拳。每一次赢的人得 11分,输的得 00 分;平局两人都得 00 分。现请你统计 NN 次猜拳结束之后两人的得分。

输入格式

第一行包含三个整数:N,NA,NBN,N_A,N_B,分别表示共进行 NN次猜拳、小 A出拳的周期长度,小 B 出拳的周期长度。数与数之间以一个空格分隔。
第二行包含 NAN_A个整数,表示小 A出拳的规律,第三行包含 NBN_B个整数,表示小 B 出拳的规律。 其中,00表示“剪刀”,11 表示“石头”,22 表示“布”,33 表示“蜥蜴人”,44表示“斯波克”。 数与数之间以一个空格分隔。

输出格式

输出一行,包含两个整数,以一个空格分隔,分别表示小 A、小 B的得分。

输入输出样例

输入 1

10 5 6
0 1 2 3 4
0 3 4 2 1 0

输出 1

6 2

输入 2

9 5 5
0 1 2 3 4
1 0 3 2 4

输出 2

4 4

说明/提示

对于100%100\%的数据,0<N200,0<NA200,0<NB2000 < N \leq 200, 0 < N_A \leq 200, 0 < N_B \leq 200

题解

思路1

这题本身非常简单,只需要把剪刀、石头、布、蜥蜴人、斯波克之间的关系搞清,简单模拟一下即可,于是写出了下面的憨批代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include<iostream>
using namespace std;
void judge(int &sa,int &sb,int a,int b)//模拟一次游戏
{
if(a==0)
{
if(b==1) sb++;
else if(b==2) sa++;
else if(b==3) sa++;
else if(b==4) sb++;
}
else if(a==1)
{
if(b==0) sa++;
else if(b==2) sb++;
else if(b==3) sa++;
else if(b==4) sb++;
}
else if(a==2)
{
if(b==0) sb++;
else if(b==1) sa++;
else if(b==3) sb++;
else if(b==4) sa++;
}
else if(a==3)
{
if(b==0) sb++;
else if(b==1) sb++;
else if(b==2) sa++;
else if(b==4) sa++;
}
else if(a==4)
{
if(b==0) sa++;
else if(b==1) sa++;
else if(b==2) sb++;
else if(b==3) sb++;
}
}
void solve()
{
int sa=0,sb=0;
int n,na,nb;
int i;
int ca[203],cb[203];
cin>>n>>na>>nb;
for(i=1;i<=na;i++) cin>>ca[i];
for(i=1;i<=nb;i++) cin>>cb[i];
int k;
//模拟循环过程
for(k=1;k*na<=201;k++)
{
for(i=1;i<=na;i++)
{
if(i+k*na<=201) ca[i+k*na]=ca[i];
}
}
for(k=1;k*nb<=201;k++)
{
for(i=1;i<=nb;i++)
{
if(i+k*nb<=201) cb[i+k*nb]=cb[i];
}
}
for(i=1;i<=n;i++) judge(sa,sb,ca[i],cb[i]);
cout<<sa<<' '<<sb;
}
int main()
{
solve();
return 0;
}

思路2

在题解区看到了一篇思路较清奇的题解,可以学习一下。

A的得分(下方为A,有方为B) 剪刀 石头 蜥蜴人 斯波克
剪刀 0 0 1 1 0
石头 1 0 0 1 0
0 1 0 0 1
蜥蜴人 0 0 1 0 1
斯波克 1 1 0 0 0
B的得分(下方为B,右方为A) 剪刀 石头 蜥蜴人 斯波克
剪刀 0 1 0 0 1
石头 0 1 0 0 1
1 0 0 1 0
蜥蜴人 1 1 0 0 0
斯波克 0 0 1 1 0

显然,A出ii,B出jj,在上述两个5×55\times 5的方阵中Mij=!Mji(ij)M_{ij}=!M_{ji}(i\ne j )
于是设计一个得分表,再让游戏次数对每一个周期取余即可。

代码2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
using namespace std;
void solve()
{
int sa=0,sb=0;
int score[5][5]={0,0,1,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,1,1,0,0,0};//计分表
int n,na,nb;
cin>>n>>na>>nb;
const int N=202;
int a[N],b[N];
int i;
//i必须从0开始,否则下面循环结构不成立
for(i=0;i<na;i++) cin>>a[i];
for(i=0;i<nb;i++) cin>>b[i];
for(i=0;i<n;i++)
{
//循环结构
sa+=score[a[i%na]][b[i%nb]];
sb+=score[b[i%nb]][a[i%na]];
}
cout<<sa<<' '<<sb;
}
int main()
{
solve();
return 0;
}