题目:
有 m 组球队, 每组有 b 支球队. 每组之间两两踢球, 赢得加2分, 平手各加1分, 输的不得分. 现在告诉你每组里面每只球队最后的分数, 问这个分数序列是否正确.
分析:
如果没有平手选项, 赢得加一分的话, 可以用Landau’s Theorem判定, 这题稍微修改下这个定理就好了. 令 s1,s2,...,sn 是他们的得分序列, 从小到大拍个序, 使得 s1≤s2≤...≤sn , 那么这个序列合法, 当且仅当:
- s1+s2+...+si≥i(i−1) , 对于所有 1≤i≤n−1
- s1+s2+...+sn=n(n−1) .
Landau’s Theorem内容:
一个长度为n的序列
s=(s1≤s2,≤...≤sn),n≥1
,是合法的比分序列当且仅当:
∀1≤k≤n,∑ki=1si≥(k2)
,且k=n时这个式子必须取等号。
代码:
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
#define lson rt*2,l,(l+r)/2
#define rson rt*2+1,(l+r)/2+1,r
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 2e5 + 5;
const double EPS = 1e-8;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int a[MAXN],n;
int main() {
int T;
while (~scanf("%d", &T)) {
while (T--) {
scanf("%d", &n);
ll tot = 0;
int ok = 1;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
tot += a[i];
}
if (tot != (ll)n * (n - 1)) ok = 0;
else {
ll res = 0;
sort(a+1,a+n+1);
for (int i = 1; i <= n; i++) {
res += a[i];
if(res < (ll)i*(i-1)){
ok = 0;
break;
}
}
}
if(ok) puts("T");
else puts("F");
}
}
return 0;
}