2012-2013 Northwestern European Regional Contest (NWERC 2012)【solved:6 / 11】
2017-09-01 14:44
447 查看
有一个大家都会的D。 emmm。我不会 但是!队友会呀2333先放放
-update:2017年10月16日20:49:39
思路:网络流。拆点入门题。s点和t点内部流量为2,其余为1。跑最小费用最大流即可。
思路:相当于一个dp[a][c][d][e],每一维度皆为50,看上去是505个状态,然而由于k只有50。相当于是5个非负整数加和为50的状态数,易得C(54,5),也就几百万个状态,所以直接宽搜即可,然后通过51进制的哈希来表示每个状态。[b]哦对了,注意!!!printf里面输出”%”是通过%%而不是%不然你会wa的不知所措orz。
思路:水题,小心一个a[i] == x - a[i]的特判即可。
思路:先按题意连边,同一段中,相同的两个字母连边。又易得,两点之间只有边数==段数,才应该在新图中连边。得到新图以后,直接搜联通块,联通块为偶数即可。(易证,今年多校也有一个这种题)然后每个联通块的贡献度即为其大小siz/2的阶乘。
-update:2017年10月16日20:49:39
A - Admiral
题意:给一张带权图,让你求出从s到t两条完全不同的路径的权值加和最小为多少。思路:网络流。拆点入门题。s点和t点内部流量为2,其余为1。跑最小费用最大流即可。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAXN = 2 * 1000 + 5; const int INF = 0x3f3f3f3f; typedef pair<int, int>pii; struct MCMF{ int n,m; struct Edge{int from, to, cap, flow, cost;}; vector<Edge> edge; vector<int> g[MAXN]; bool inq[MAXN]; int d[MAXN]/*spfa*/, pre[MAXN]/*上一条弧*/, a[MAXN]/*可改进量*/; void init(int n){ this->n = n; for(int i = 1; i <= n; i++) g[i].clear(); edge.clear(); } void addedge(int from, int to, int cap, int cost) { edge.push_back({from,to,cap,0,cost}); edge.push_back({to,from,0,0,-cost}); m = edge.size(); g[from].push_back(m-2); g[to].push_back(m-1); } bool spfa(int s, int t, int& flow, LL& cost) { for(int i = 1; i <= n; i++) inq[i] = 0, d[i] = INF; d[s] = 0, inq[s] = true, pre[s] = 0, a[s] = INF; queue<int> q; q.push(s); while(!q.empty()) { int u = q.front();q.pop(); inq[u] = false; for(int i = 0; i < g[u].size(); i++) { Edge& e = edge[g[u][i]]; if(e.cap > e.flow && d[e.to] > d[u]+e.cost) { d[e.to] = d[u]+e.cost; pre[e.to] = g[u][i]; a[e.to] = min(a[u], e.cap-e.flow); if(!inq[e.to]) q.push(e.to), inq[e.to] = true; } } } if(INF == d[t]) return false; flow += a[t]; cost += (LL)d[t]*(LL)a[t]; for(int u = t; u != s; u = edge[pre[u]].from) { edge[pre[u]].flow += a[t]; edge[pre[u]^1].flow -= a[t]; } return true; } //需要保证初始网络没有负圈,返回最大流量,cost才是最小花费 int mincostmaxflow(int s, int t, LL & cost) { int flow = 0; cost = 0; while(spfa(s,t,flow,cost)); return flow; } }mcmf; int main() { int vs, es; while(~scanf("%d%d", &vs, &es)) { mcmf.init(vs << 1); for(int i = 2; i < vs; i++) mcmf.addedge(i, i + vs, 1, 0); mcmf.addedge(1, vs + 1, 2, 0); mcmf.addedge(vs, vs << 1, 2, 0); for(int i = 0; i < es; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); mcmf.addedge(a + vs, b, 1, c); } long long ans = 0; mcmf.mincostmaxflow(1, vs << 1, ans); printf("%lld\n", ans); } return 0; }
B - Beer Pressure(搜索+哈希状态)
题意:给你n个人已获得的票数,告诉你参与投票的人总人数为K,问你每个人赢得最后获选的概率是多少。每个人投票时,投票概率不等价,投第i个人的概率为,第i个人当前获得票数/当前已投票人数。如果最后k票投完,有人同为票数最高者,平分胜率。(n≤5,k≤50)思路:相当于一个dp[a][c][d][e],每一维度皆为50,看上去是505个状态,然而由于k只有50。相当于是5个非负整数加和为50的状态数,易得C(54,5),也就几百万个状态,所以直接宽搜即可,然后通过51进制的哈希来表示每个状态。[b]哦对了,注意!!!printf里面输出”%”是通过%%而不是%不然你会wa的不知所措orz。
#include <bits/stdc++.h> using namespace std; const int base = 51; int n, k, pub[10], temp[10]; double ans[10]; inline long long calc(int a[]) { long long ret = 0; for(int i = 0; i < n; i++) ret = ret * base + a[i]; return ret; } int main() { while(~scanf("%d%d", &n, &k)) { for(int i = 0; i < n; i++) ans[i] = 0; for(int i = 0; i < n; i++) scanf("%d", &pub[i]); unordered_map<long long, double>pro; queue<long long>que; que.push(calc(pub)); pro[calc(pub)] = 1.0; while(que.size()) { long long cur = que.front();que.pop(); long long tot = 0; for(int i = 0; i < n; i++) temp[n - 1 - i] = cur % base, cur /= base, tot += temp[n - 1 - i]; long long st = calc(temp); if(tot == k) { int mx = *max_element(temp, temp + n); int cnt = count(temp, temp + n, mx); for(int i = 0; i < n; i++) if(temp[i] == mx) ans[i] += 1.0 / cnt * pro[st]; continue; } for(int i = 0; i < n; i++) { double p = 1.0 * temp[i] / tot; temp[i]++; long long fst = calc(temp); if(pro[fst] == 0) que.push(fst); pro[fst] += pro[st] * p; temp[i]--; } } for(int i = 0; i < n; i++) printf("pub %d: %.2f %%\n", i + 1, ans[i] * 100); } return 0; }
E - Edge Case
思路:写了几个发现感觉是斐波那契数列,直接加了个大数类A了。I - Idol
2-SAT板子题。#include <bits/stdc++.h> using namespace std; const int maxn = 2000 + 5; vector<int>G[maxn]; int pre[maxn]; int lowlink[maxn];//lowlink[u]:u及其后代能追溯到的最早祖先点v的pre[v]的值。 int sccno[maxn], dfs_clock, scc_cnt; stack<int>S; void Tarjan(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(pre[v] == 0) { Tarjan(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if(!sccno[v]) { lowlink[u] = min(lowlink[u], pre[v]); } } if(lowlink[u] == pre[u]) { scc_cnt++; for(;;) { int x = S.top();S.pop(); sccno[x] = scc_cnt; if(x == u) break; } } } void find_scc(int n) { dfs_clock = scc_cnt = 0; memset(sccno, 0, sizeof(sccno)); memset(pre, 0, sizeof(pre)); for(int i = 1; i <= n; i++) { if(pre[i] == 0) Tarjan(i); } } int n, m; int ans[maxn]; pair<int, int>a[maxn]; bool solve() { memset(ans, 0, sizeof(ans)); for(int i = 1; i <= n; i++) { if(sccno[i] == sccno[i + n]) return false; } int flag = 0; if(sccno[1] > sccno[1 + n]) flag = 1; for(int i = 1; i <= n; i++) { if(flag) ans[i] = (sccno[i] > sccno[i + n]); else ans[i] = (sccno[i] < sccno[i + n]); } for(int i = 0; i < m; i++) { int x = a[i].first, y = a[i].second; int jx = (x > 0), jy = (y > 0); x = abs(x), y = abs(y); if((ans[x] != jx) && (ans[y] != jy)) return false; } return true; } int main() { while(~scanf("%d%d", &n, &m)) { for(int i = 1; i <= 2 * n; i++) G[i].clear(); for(int i = 0; i < m; i++) { int x, y; scanf("%d%d", &x, &y); a[i] = {x, y}; if(x > 0 && y > 0)//x && y G[x + n].push_back(y), G[y + n].push_back(x); else if(x < 0 && y < 0) { x = abs(x), y = abs(y); G[x].push_back(y + n), G[y].push_back(x + n); } else if(x > 0 && y < 0) { y = abs(y); G[x + n].push_back(y + n); G[y].push_back(x); } else if(x < 0 && y > 0) { swap(x, y); y = abs(y); G[x + n].push_back(y + n); G[y].push_back(x); } } find_scc(2 * n); if(solve()) puts("yes"); else puts("no"); } return 0; }
J - Joint Venture
题意:给你n个数,问你里头有没有两个加和为x的。(0≤n≤1e6,x≤1e8)思路:水题,小心一个a[i] == x - a[i]的特判即可。
K - Key Insight
题意:给你两串字符,然后告诉你长度k为一段,串一串二在每一段中一一对应,得到若干种对应方案,然后问你整个串中有多少种方案使得,所有段均满足。思路:先按题意连边,同一段中,相同的两个字母连边。又易得,两点之间只有边数==段数,才应该在新图中连边。得到新图以后,直接搜联通块,联通块为偶数即可。(易证,今年多校也有一个这种题)然后每个联通块的贡献度即为其大小siz/2的阶乘。
#include <bits/stdc++.h> using namespace std; char s1[105], s2[105]; int pre[205][205], in[205], vis[205]; vector<int>G[205]; int siz = 0; int dfs(int u) { vis[u] = 1; int ret = 1; for(auto o : G[u]) if(vis[o] == 0) ret += dfs(o); return ret; } long long fac(int siz){long long ret = 1;for(int i = 1; i <= siz; i++) ret *= i; return ret;}; int main() { int block; while(~scanf("%d", &block)) { memset(vis, 0, sizeof(vis)); memset(pre, 0, sizeof(pre)); for(int i = 0; i <= 200; i++) G[i].clear(); scanf("%s%s", s1 + 1, s2 + 1); int len = strlen(s1 + 1); int need = len / block; for(int i = 1; i <= len; i += block) { for(int j = 0; j < block; j++) { for(int k = 0; k < block; k++) { if(s1[j + i] == s2[k + i]) { pre[j + 1][k + 1 + block]++, pre[k + 1 + block][j + 1]++; } } } } for(int i = 1; i <= block * 2; i++) { for(int j = block + 1; j <= block * 2; j++) { if(pre[i][j] >= need) { G[i].push_back(j); G[j].push_back(i); in[i]++, in[j]++; } } } long long ans = 1; for(int i = 1; i <= block; i++) { if(vis[i]) continue; int siz = dfs(i); if(siz & 1) ans = 0; else ans *= fac(siz/2); } printf("%I64d\n", ans); } return 0; }
相关文章推荐
- 2014-2015 Northwestern European Regional Contest (NWERC 2014)【solved:7 / 11】
- 2015-2016 Northwestern European Regional Contest (NWERC 2015) 7/11 待补
- 2013-2014 Northwestern European Regional Contest (NWERC 2013)
- 2017-2018 Northwestern European Regional Contest (NWERC 2017)
- 2015-2016 Northwestern European Regional Contest (NWERC 2015) 补题
- Codeforces-20152016-northwestern-european-regional-contest-nwerc-A题
- 2015-2016 Northwestern European Regional Contest (NWERC 2015)
- Editing 2011-2012 ACM-ICPC Northeastern European Regional Contest (NEERC 11)
- 2015-2016 Northwestern European Regional Contest (NWERC 2015) E
- E - Elementary Math 2015-2016 Northwestern European Regional Contest (NWERC 2015)
- I - Identifying Map Tiles 2015-2016 Northwestern European Regional Contest (NWERC 2015)
- C-Cleaning Pipes(判断两线段相交+二分图判定) 2015-2016 Northwestern European Regional Contest (NWERC 2015)
- codeforces Gym - 101485 D Debugging (2015-2016 Northwestern European Regional Contest (NWERC 2015))
- J - Jumbled Communication 2015-2016 Northwestern European Regional Contest (NWERC 2015)
- 2012-2013 ACM-ICPC Northeastern European Regional Contest (NEERC 12)
- codeforces Gym - 101485 A (2015-2016 Northwestern European Regional Contest (NWERC 2015))
- 2015-2016 Northwestern European Regional Contest (NWERC 2015) E. Elementary Math
- D - Debugging 2015-2016 Northwestern European Regional Contest (NWERC 2015)
- 2016-2017 ACM-ICPC Northwestern European Regional Programming Contest (NWERC 2016)
- 2012-2013 ACM-ICPC East Central North America Regional Contest (ECNA 2012)