题目信息
题目传送门
解题思路
法1:纯模拟(T(n) + O(n))
模拟n比赛,用两个变量记录两个人出到周期的第几位了,然后判断谁能赢。
法2:数学优化(T(min{n, na * nb / GCD(na, nb)}) + O(n))
- 若n ≤ na * nb,即小A和小B已经重新回到na1对nb1了,那么直接按照法1模拟一遍就ok。
- 否则,我们管一次na1对nb1到下一次na1对nb1的过程叫做一个大周期,那么:
我们的解题思路就是算出每个大周期内小A和小B的得分乘上大周期数,再单独模拟剩下的部分。 这样做明显比纯模拟要快。
代码实现
法1
#include <bits/stdc++.h>
using namespace std;
const int score[6][6] = { {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 A[205], B[205];
int main() {
int n, na, nb;
cin >> n >> na >> nb;
for (int i = 1; i <= na; ++i) {
cin >> A[i];
}
for (int i = 1; i <= nb; ++i) {
cin >> B[i];
}
int a = 1, b = 1;
int suma = 0, sumb = 0;
for (int i = 1; i <= n; ++i) {
suma += score[A[a]][B[b]];
sumb += score[B[b]][A[a]];
if (a == na) {
a = 1;
} else {
++a;
}
if (b == nb) {
b = 1;
} else {
++b;
}
}
cout << suma << ' ' << sumb << '\n';
return 0;
}
法2
#include <bits/stdc++.h>
using namespace std;
const int score[6][6] = { {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 A[205], B[205];
int main() {
int n, na, nb;
cin >> n >> na >> nb;
for (int i = 1; i <= na; ++i) {
cin >> A[i];
}
for (int i = 1; i <= nb; ++i) {
cin >> B[i];
}
int suma = 0, sumb = 0;
if (na * nb >= n) {
for (int i = 0; i < n; ++i) {
suma += score[A[i % na + 1]][B[i % nb + 1]];
sumb += score[B[i % nb + 1]][A[i % na + 1]];
}
} else {
for (int i = 0; i < na * nb; ++i) {
suma += score[A[i % na + 1]][B[i % nb + 1]];
sumb += score[B[i % nb + 1]][A[i % na + 1]];
}
int m = n / (na * nb);
suma *= m;
sumb *= m;
for (int i = 0; i < n - m * na * nb; ++i) {
suma += score[A[i % na + 1]][B[i % nb + 1]];
sumb += score[B[i % nb + 1]][A[i % na + 1]];
}
}
cout << suma << ' ' << sumb << '\n';
return 0;
}
|