AtCoder Regular Contest 105
阿新 • • 發佈:2021-12-22
菜的真實
T3,T4卡大題還行
C - Camels and Bridge
首先看資料範圍肯定不是一個多項式複雜度的演算法
考慮列舉全排列,那麼怎麼判斷頭尾最短的長度是多少呢?
其實也不難,只要把每個連續段開到必須要開長度,然後大的繼承小的即可
具體實現可以看程式碼
code:
#include<bits/stdc++.h> using namespace std; const int N = (1 << 8) + 5; int n, m, a[15], sum[N], g[N], f[15], id[15]; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) scanf("%d", &a[i]); sort(a + 1, a + 1 + n); for(int S = 0; S < (1 << n); S ++) for(int i = 1; i <= n; i ++) if((S >> (i - 1)) & 1) sum[S] += a[i]; while(m --) { int l, s; scanf("%d%d", &l, &s); if(s < a[n]) { printf("-1"); return 0; } for(int S = 0; S < (1 << n); S ++) if(sum[S] > s) g[S] = max(g[S], l); } for(int i = 1; i <= n; i ++) id[i] = i; int ans = 1e9; do { for(int i = 1; i <= n; i ++) f[i] = 0; for(int i = 1; i <= n; i ++) { int S = (1 << (id[i] - 1));; for(int j = i + 1; j <= n; j ++) { S |= (1 << (id[j] - 1)); f[j] = max(f[j], f[i] + g[S]); } } ans = min(ans, f[n]); } while(next_permutation(id + 1, id + 1 + n)); printf("%d", ans); return 0; }
D - Let's Play Nim
可以看出來要滿足全部移到盤子後,最後一個人要儘量讓盤子上的抑或和為0,否則下一個人必勝
那麼如果\(n\)為奇數,最後一次移動一定是先手,那麼後手只需要瞎搗亂,把一半以上的疊到一個上面就行了所以後手必贏
如果\(n\)為偶數,如果可以對稱的放(即每個數出現次數都是偶數次)那麼後手必勝,否則先手必勝
code:
#include<bits/stdc++.h> #define N 200050 using namespace std; int n, a[N]; void solve() { scanf("%d", &n); for(int i = 1; i <= n; i ++) scanf("%d", &a[i]); if(n & 1) { printf("Second\n"); return ; } sort(a + 1, a + 1 + n); //for(int i = 1; i <= n; i ++) printf("%d ", a[i]); printf("\n"); for(int i = 2; i <= n; i += 2) if(a[i] != a[i - 1]) { printf("First\n"); return ; } printf("Second\n"); } int t; int main() { scanf("%d", &t); while(t --) solve(); return 0; }
E - Keep Graph Disconnected
又是博弈
如果
賀一發楊隊的分析
code:
#include<bits/stdc++.h> #define N 200050 using namespace std; int vis[N], n, m, gs; vector<int> g[N]; void dfs(int u) { if(vis[u]) return ; gs ++; vis[u] = 1; for(int v : g[u]) dfs(v); } void solve() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) g[i].clear(), vis[i] = 0; for(int i = 1; i <= m; i ++) { int u, v; scanf("%d%d", &u, &v); g[u].push_back(v), g[v].push_back(u); } if(n & 1) { if((1ll * n * (n - 1) / 2 - m) & 1) printf("First\n"); else printf("Second\n"); return ; } gs = 0; dfs(1); int s = gs; gs = 0; dfs(n); int ss = gs; if((s + ss) & 1) { printf("First\n"); return ; } if((1ll * n * (n - 1) / 2 - 1ll * s * ss - m % 2) & 1) printf("First\n"); else printf("Second\n"); } int t; int main() { scanf("%d", &t); while(t --) solve(); return 0; }