A. Destroying Bridges(思维)
#include<iostream>
using namespace std;
int main(){
int t;
scanf("%d", &t);
int n, k;
while(t--){
scanf("%d%d", &n, &k);
if(k < n - 1) printf("%d\n", n);
else printf("1\n");
}
return 0;
}
B. Equal XOR(异或)
首先考虑两边的数都是一样的,那毫无疑问全部XOR结果相等;再考虑下两边的某两个不等的数调换位置,那么两边会出现对子,对子XOR为0,其他数仍旧一致,那全部XOR结果依旧相等;而给出的数组肯定可以通过有限次对调由两边一样的数组得到;
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], c[N];
int res1[N], res2[N];
int main(){
int t;
scanf("%d", &t);
int n, k;
while(t--){
scanf("%d%d", &n, &k);
for(int i = 1; i <= 2 * n; i++){
scanf("%d", &a[i]);
b[i] = 0;
c[i] = 0;
}
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= n; i++){
b[a[i]]++;
if(b[a[i]] == 2 && cnt1 < 2 * k){
res1[++cnt1] = a[i];
res1[++cnt1] = a[i];
}
}
if(cnt1 < 2 * k){
for(int i = 1; i <= N; i++){
if(b[i] == 1) res1[++cnt1] = i;
if(cnt1 == 2 * k) break;
}
}
for(int i = n + 1; i <= n * 2; i++){
c[a[i]]++;
if(c[a[i]] == 2 && cnt2 < 2 * k){
res2[++cnt2] = a[i];
res2[++cnt2] = a[i];
}
}
if(cnt2 < 2 * k){
for(int i = 1; i <= N; i++){
if(c[i] == 1) res2[++cnt2] = i;
if(cnt2 == 2 * k) break;
}
}
for(int i = 1; i <= cnt1; i++) printf("%d ", res1[i]);
printf("\n");
for(int i = 1; i <= cnt2; i++) printf("%d ", res2[i]);
printf("\n");
}
return 0;
}
C. MEX Game 1(博弈)
如果这个数在数组中出现了两次或以上的次数,那么bob必然无法阻止Alice选中(因为bob选一次后Alice就可以选这个数),所以bob应该首选最小的且数组中只有一个的数,但是为Alice先选,换个角度也就是说Alice可以“救”一个数,所以最小值应为数组中只有一个且第二小的数。(当然如果存在一个数没有出现且比上面得到的数小,那么最小应为没出现的数)
#include<iostream>
#include<cstring>
using namespace std;
const int N = 2e5 + 10;
int a[N], b[N];
int main(){
int t;
scanf("%d", &t);
int n, k;
while(t--){
memset(b, 0, sizeof(b));
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
b[a[i]]++;
}
int cnt = 0, ans;
for(int i = 0; i <= N; i++){
if(b[i] == 1) cnt++;
if(b[i] == 0) cnt += 2;
if(cnt >= 2){
ans = i;
break;
}
}
printf("%d\n", ans);
}
return 0;
}