此题, 是一个模拟题,难度应该不超过leetcode 中等。两人的出手是按一定周期依次排列的,那么输赢的结果自然也是按照一定周期排列的,这个周期就是两人出牌周期的最小公倍数,按此思路,则可编写代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char a[1010], b[1010];
int lena, lenb, n;
// 判断输赢
int judge(char a, char b)
{
if (a == b) return 0; // 平局
if (a == 'R' && b == 'S' || a == 'S' && b == 'P' || a == 'P' && b == 'R') return 1; // a赢
return 2; // b赢
}
// 求最大公约数
int gcd(int x, int y)
{
return !y ? x : gcd(y, x % y);
}
// 求最小公倍数
int lcm(int x, int y)
{
return x / gcd(x, y) * y;
}
int main()
{
scanf("%d", &n);
scanf("\n%s\n%s", a, b);
lena = strlen(a);
lenb = strlen(b);
int resa = 0, resb = 0; // a、b输的次数
int T = lcm(lena, lenb); // A,B 两人出手的周期
if (n <= T)
{
// 未满一个周期 直接循环模拟n次
for (int i = 0; i < n; i ++ )
{
int t = judge(a[i % lena], b[i % lenb]); // i % lena 确保不越界且能循环
if (t == 1) resb ++ ;
else if (t == 2) resa ++ ;
}
}
else
{
// 满一个周期 计算一个周期内输的次数乘以倍数再加上相应余数
int r = n % T;
int resa_t = 0, resb_t = 0;
for (int i = 0; i < T; i ++ )
{
int t = judge(a[i % lena], b[i % lenb]);
if (t == 1)
{
if (i < r) resb ++ ;
resb_t ++ ;
}
else if (t == 2)
{
if (i < r) resa ++ ;
resa_t ++ ;
}
}
resa += resa_t * (n / T);
resb += resb_t * (n / T);
}
cout << resa << " " << resb << endl;
return 0;
}