问题 I: 游戏

题目描述
今天是星期天,小楠楠来找你玩“石头、剪刀、布游戏”。你正在学习信息学,所以想了一种需要编程来玩的“石头、剪刀、布游戏”。首先,用数字1,2,3分别表示出石头、剪刀、布。其次,你确定自己前N次“石头、剪刀、布”的出拳方法,下面N次再次同样出拳,…,周而复始;也要求楠楠确定他前M次的出拳方法,然后周而复始。问第K次后,你赢了几次?
例如:N=4,你的前4次出拳方式是“石头、剪刀、布、布”,用数字表示即:”1 2 3 3”。M=5,楠楠前5次出拳方式是“剪刀、石头、石头、布、布” ,用数字表示即:”2 1 1 3 3”。K=10时,情况如下表:
在这里插入图片描述

你共赢了5次。

输入
第一行3个整数N,M,K。分别表示你出拳方式的周期长度、楠楠出拳方式的周期长度和总共玩的次数。
第二行有N个整数,每个整数为1、2、3其中之一。
第三行有M个整数,每个整数为1、2、3其中之一。
输出
一个整数,表示K轮出拳后,你赢的次数。
样例输入 Copy
5 6 100
1 3 2 2 1
3 3 1 1 1 2
样例输出 Copy
29
提示
8个数据: N,M 的范围是[1…100],K的范围是[1…100,000]。
2个数据: N,M的范围是[1…100],K的范围是[1…1,000,000,000]
#include
#include
using namespace std;
int gcd(int x,int y){//辗转相除法求最小公倍数
if(y==0)return x;
else return gcd(y,x%y);
}
int main(void){
int N,M,K;
int c1=0;
int c2=0;
scanf("%d%d%d",&N,&M,&K);
int arrn[100];
int arrm[100];
for(int i=0;i<N;i++){
scanf("%d",&arrn[i]);
}
for(int i=0;i<M;i++){
scanf("%d",&arrm[i]);
}
int g=(MN)/gcd(N,M);
for(int i=0;i<g;i++){
if(arrn[i%N]==1&&arrm[i%M]==2){c1++;}
if(arrn[i%N]==2&&arrm[i%M]==3){c1++;}
if(arrn[i%N]==3&&arrm[i%M]==1){c1++;}
}
c1
=(K/g);
int g2=K%g;
for(int i=0;i<g2;i++){
if(arrn[i%N]==1&&arrm[i%M]==2){c2++;}
if(arrn[i%N]==2&&arrm[i%M]==3){c2++;}
if(arrn[i%N]==3&&arrm[i%M]==1){c2++;}
}
printf("%d",c1+c2);
return 0;
}
思路解析:依然是不考虑太多的话很好做但是时间会超,仔细分析会发现,N的胜场每经过N和M的最小公倍数会重复,一个周期*周期数+剩下的胜场(两个数的最小公倍数是两个数的乘积除以两个数的最大公约数)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值