题意
进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛时,游戏结束。
现在给出n次对决的输赢情况,问可能的s和t有多少种,并按s递增的方式输出
解析
若使用暴力,10000*10000的时间复杂度会超时,所以要另寻他法。
由于一个人满足t分一局比赛就结束,当一个人赢了s局,比赛结束。
所以我们要遍历t,但是每当一个人达到t分,我们就要舍弃另一个人的分数,下一局便从这个人位置的pos+1,开始算,所以我们要记录这两个人达到t分的位置。之后用每个t分的整数倍去找每个人赢了几局。但要记录是否一个人刚好把最后一场比完后,比赛结束了。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<vector>
using namespace std;
const int maxn = 200000+10;
int p[maxn], g[maxn];
typedef pair<int, int> P;
vector<P>ve;
int main() {
int n;
while (~scanf("%d", &n)) {
int a, b;
a = b = 0;
memset(p, 0, sizeof(p));
memset(g, 0, sizeof(g));
ve.clear();
for (int i=1; i<=n; i++) {
int x;
scanf("%d", &x);
if (x == 1)
a++, p[a] = i;
else
b++, g[b] = i;
}
int P, G, maxt, j;
for (int i=1; i<=2*n; i++) {
if (p[i] == 0)
p[i] = n+1;
if (g[i] == 0)
g[i] = n+1;
}
for (int i=1; i<=n; i++) {
P = G = maxt = 0;
j = a = b = 0;
while (j<n) {
if (p[i+a] < g[i+b]) {
P++;
maxt = P;
j = p[i+a];
a += i;
b = j-a;
}
else {
G++;
maxt = G;
j = g[i+b];
b += i;
a = j-b;
}
//cout<<j<<endl;
}
if (j == n && P != G && max(P, G) == maxt) {
ve.push_back(make_pair(maxt, i));
}
}
sort(ve.begin(), ve.end());
printf("%d\n", (int)ve.size());
for (int i=0; i<ve.size(); i++) {
printf("%d %d\n", ve[i].first, ve[i].second);
}
}
return 0;
}