UESTC - 第12届 ACM 趣味赛一
A
略
B
先假设没有 ”知道这 \(n\) 个人中普通市民的人数一定不少于组织中的人“ 这个条件,我们考虑为什么没有办法将任何人的身份识别出来。不妨这样想:每一个人只有两种情况,要么说谎话,要么说真话,而所有说谎话的人和所有说真话的人给出的答案都会是一样的。也就是说,我们只可能得到两种答案,要么是真实的情况,要么是真实的情况取反(即,说谎话会被认为是说真话,说真话会被认为是说假话)。很显然对于这两种答案我们没法判断出那个是正确的,但是我们可以获得一个信息,也就是这群人已经被分为两群,要么其中一群是诚实的,另一群是不诚实的;要么其中一群是不诚实的,另一群是诚实的。现在加上前面提到的那个条件,我们发现当这两群人人数不等的时候,人数多的一定是普通市民;只有当人数相等的时候,无法将这两群人归类,此时总人数为偶数。答案显然。
C
方法一
设 \(f[i][j]\) 表示前 \(i\) 关 Kaiser 玩 \(j\) 局而 Fatdog_Jo 玩 \(i-j\) 局的最少时间,则转移方程为 \(f[i][j]=max\{f[i-1][j]+b[i],f[i-1][j-1]+a[i]\}\) ,该方法时间复杂度为 \(O(n^2)\)。
方法二
先假设所有关都由 Fatdog_Jo 来玩,则 \(ans=\sum b[i]\)。设 \(c[i]=a[i]-b[i]\),则若第 \(i\) 关由 Kaiser 来玩,我们只需将 \(ans+=c[i]\)。现在有 \(n/2\) 关需要 Kaiser 来玩,我们只需要从 \(c[i]\) 中选出最小的 \(n/2\) 个加上去即可。该方法时间复杂度为 \(O(n\log n)\) 优于方法一。
D
暴力枚举旋风斩的回合数即可,显然最多不超过 \(5000\) 次旋风斩所有随从会死亡。时间复杂度为 \(O(na)\)。
E
设 \(t\) 时刻成员 \(0\) 与成员 \(1\) 相遇,列出方程组:
1:\(y_0=ax_0+b\)
2:\(y_1=ax_1+b\)
3:\(x_0+v_{x_0}t=x_1+v_{x_1}t\)
4:\(y_0+v_{y_0}t=y_1+v_{y_1}t\)
由 3 得 \(x_0-x_1=-t(v_{x_0}-v_{x_1})\)
由 4 得 \(y_0-y_1=-t(v_{y_0}-v_{y_1})\)
两式相除,整理得 \(v_{y_0}-v_{y_1}=a(v_{x_0}-v_{x_1})\)
移项得 \(v_{y_0}-av_{x_0}=v_{y_1}-av_{x_1}\)
即当上式成立(两直线平行除外)时两个成员相遇。特判一下平行的情况以及 \(a=0\) 的情况即可(\(Upd\):\(a=0\)不用特判)。
Code
#include <cstdio>
#include <map>
#include <utility>
using namespace std;
int n, a, b, x, y;
long long ans;
map<int, int> mp;
map<pair<int, int>, int> mppar;
int main(){
scanf("%d%d%d", &n, &a, &b);
if(!a){
for(int i = 0; i < n; i++){
scanf("%d%d%d", &x, &x, &y);
ans += mp[y] - mppar[make_pair(x, y)];
mp[y]++, mppar[make_pair(x, y)]++;
}
}else for(int i = 0; i < n; i++){
scanf("%d%d%d", &x, &x, &y);
ans -= mppar[make_pair(x, y)];
mppar[make_pair(x, y)]++;
x = y - a * x;
ans += mp[x];
mp[x]++;
}
printf("%lld", ans << 1);
return 0;
}