A - 关押罪犯(并查集)
B - 能量项链(区间DP)
题解:
状态表示:
1.集合:所有将[i, j]合并成一堆的方案
2.属性:max
状态计算:
把头看成区间左端点,尾看成区间右端点。因为最后一个的尾部和第一个的头相连,所以就组成了一个圈。这个圈可以理解成把坐标轴围成圈。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200 + 7;
#define inf 0x3f3f3f3f
ll n, energy[N], f[N][N];
int main(){
cin >> n;
for (int i = 1; i <= n; ++i){
cin >> energy[i];//输入的时候只输入头部的值
energy[i + n] = energy[i];//后一个头部 = 前一个尾部,并且最后一个的尾部 = 第一个的头部,从而算出所有的尾部的值。
}
energy[2*n + 1] = energy[1];//因为最后一个的尾部和第一个的头相连
memset(f, 0, sizeof f);
for (int len = 2; len <= n; ++len){//枚举区间长度
for (int i = 1; i + len - 1 < 2 * n; ++i){//i + len - 1是区间右端点(即珠子尾部)
int j = i + len - 1;//区间右端点
for (int k = i; k < j; ++k){//连接上区间里的所有珠子
f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j] + energy[i] * energy[k + 1] * energy[j + 1]);
}
}
}
ll mmax = 0;
for (int i = 1; i <= n; ++i){
mmax = max(mmax, f[i][i + n - 1]);//找最大值
}
cout << mmax << endl;
return 0;
}
G - 小约翰的游戏John(反nim游戏)
详细讲解:
尼姆博弈(前面是尼姆博弈后面是反尼姆博弈)
反尼姆博弈
题解:
标准的anti-nim游戏:
[定义](anti-nim 游戏)
桌子上有 N 堆石子,游戏者轮流取石子。
每次只能从一堆中取出任意数目的石子,但不能不取。
取走最后一个石子者败。
[结论]
先手必胜当且仅当:
(1)所有堆的石子数都为 1 且游戏的 SG 值为 0;
(2)有些堆的石子数大于 1 且游戏的 SG 值不为 0。
[证明]
游戏分两种情况:
有 N 个堆,每个堆只有一个石子。
显然,先手必胜当且仅当 N 为偶数。
其他情况。
(1) 当 SG 不为 0 时
若还有至少两堆石子的数目大于 1,则先手将 SG 值变为 0 即可;
若只有一堆石子数大于 1,则先手总可以将状态变为有奇数个 1。所
以,当 SG 不为 0 时先手必胜。
(2) 当 SG 为 0 时
至少有两堆石子的数目大于 1,则先手决策完之后,必定至少有
一堆的石子数大于 1,且 SG 值不为 0,由上段的论证我们可以发现,
此时,无论先手如何决策,都只会将游戏带入先手必胜局,所以先
手必败。–贾志豪
AC代码:
#include <iostream>
using namespace std;
int n, x, t;
int res;
bool flag;
int main(){
cin >> t;
while(t--){
cin >> n;
res = 0;
flag = 0;
for(int i = 0; i < n; i++){
cin >> x;
res ^= x;
if(x > 1){
flag = 1;
}
}
if(flag == 0){
if(n % 2 == 1){
cout << "Brother";
}
else{
cout << "John";
}
}
else{
if(res){
cout << "John";
}else{
cout << "Brother";
}
}
cout << endl;
}
return 0;
}
H - 聪明的猴子
知识点:
最小生成树
I - 程序自动分析
J - 超级英雄Hero
知识点:
1.二分图匹配
2.匈牙利算法:
二分图匹配
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 03f3f3f3f
const int N = 1e3 + 7;
int used[N][N],link[N];
int n,m;
bool book[N];
bool find(int x){
for(int i = 0; i < n; i++){
if(!book[i] && used[x][i]){
book[i] = 1;
if(!link[i] || find(link[i])){
link[i] = x;
return 1;
}
}
}
return 0;
}
int main(){
cin >> n >> m;
for(int i = 1; i <= m; i++){
int x,y;
cin >> x >> y;
used[i][x] = used[i][y] = 1;
}
int ans = 0;
for(int i = 1 ; i <= m; i++){
memset(book, 0, sizeof(book));
if(find(i)) ans++;
else break;
}
cout << ans << endl;
return 0;
}
L - Circle Game
对称博弈:
若博弈的收益只依赖于选手所选择的策略而不依赖于进行博弈的选手,则称为对称博弈。
结论 : 对于最大的k值使得(kz,kz)仍在圆内,((k+1)z,kz)在圆内玩家1赢,否则玩家2赢
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t, d, k, z;
int main(){
cin >> t;
while(t--){
cin >> d >> k;
z = (d * d) / (2 * k * k);
z = sqrt(z);
if((k * z) * (z * k) + (z + 1) * (z + 1) * k * k > d * d) cout << "Utkarsh" << endl;
else cout << "Ashish" << endl;
}
return 0;
}
M - Unique Bid Auction
暴力+STL。