2014 Multi-University Training Contest 6 部分题目解题报告
2014-08-08 19:50
183 查看
http://acm.hdu.edu.cn/search.php?field=problem&key=2014%20Multi-University%20Training%20Contest%206&source=1&searchmode=source
HDOJ 4921 Map
题意:
模型转化为:给不超过10条链,每条链不超过1000个点,每条链可以选前缀的一段或是不选,每一种选法都会得到分数,分数又分成两步计算(还挺麻烦,不解释了),现在让你随便选,问选出来的分数期望是多少。
分析:
每种选法是等概率的,所以所求期望就是 Σ每个方案的分数/总方案数。总方案数就是所有链的长度+1的乘积,再-1(去掉都不选的情况)。考虑每种方案的分数很复杂,其实可以考虑每个点的分数会被取多少次。对于第一步,每个点就是自己的分数乘以会包含该点的方案数,即是其他链的取法的乘积乘上该点到该链末尾的长度。然后第二步就是考虑每一个等级(1000),然后2^10暴力枚举每条链该等级选或不选,累加即可。题解没仔细看,貌似更很厉害些,还有个log的复杂度=。=。。。
HDOJ 4923 Room and Moor
题意:
给定序列Ai,只有0和1,你要选择一个序列Bi,满足单调非递减,每一项范围在[0,1]的条件,使得Σ(Ai - Bi)^2最小。
分析:
先考虑贪心,前面连续的0和末尾连续的1都可以去掉,每当碰上0,不用上升,如果是1,考虑上升和上升的高度,然后就跪了。可以想象最后的Bi应该是一条条高度上升的线段,也就是从l到r的一段区间,Bl..Bi..Br的值相同,对所求式子求导,或是直接展开成一个二次函数,会发现对于一段区间,Bi的最优值等于Ai中对应区间的1的个数除以1和0的个数(即区间长度)。通过这样的方式来贪心处理不了100...000111...110这种情况。其实可以引入单调栈让我们有“反悔”的机会。单调栈里存的是之前的区间的Bi的大小,显然是递增的。我们加入新的区间(开始就是新的点),计算它的Bi最优值,如果比栈顶的高,我们就加入栈。如果比栈顶低,我们就把栈顶区间取出,和当前区间合并,再和新栈顶比较,直到比某个栈顶高或者栈空,将合并后的区间压入栈。最后扫描一遍栈求出答案即可。
HDOJ 4925 Apple Tree
题意:
n×m的图,每格可以种苹果或施肥,种苹果得一个苹果,施肥的格子上下左右的格子若种苹果则苹果数翻倍,问最多能得几个苹果。
分析:
本场签到题,观察发现黑白染色可以获得最多的苹果。范围很小,可以直接染色求结果,推公式也很快。(提示:先考虑1×m的情况,再考虑2×m的情况,推广到n×m的情况)
View Code
HDOJ 4921 Map
题意:
模型转化为:给不超过10条链,每条链不超过1000个点,每条链可以选前缀的一段或是不选,每一种选法都会得到分数,分数又分成两步计算(还挺麻烦,不解释了),现在让你随便选,问选出来的分数期望是多少。
分析:
每种选法是等概率的,所以所求期望就是 Σ每个方案的分数/总方案数。总方案数就是所有链的长度+1的乘积,再-1(去掉都不选的情况)。考虑每种方案的分数很复杂,其实可以考虑每个点的分数会被取多少次。对于第一步,每个点就是自己的分数乘以会包含该点的方案数,即是其他链的取法的乘积乘上该点到该链末尾的长度。然后第二步就是考虑每一个等级(1000),然后2^10暴力枚举每条链该等级选或不选,累加即可。题解没仔细看,貌似更很厉害些,还有个log的复杂度=。=。。。
#include<cstdio> #include<cstring> using namespace std; int T, n, m, x, y, tot; int nex[10100], v[10100], line[15][1010]; bool head[10100]; double sum, sumv; void dfs(int lv, int pos, int yi, int sumi, int xi, double sum) { if (pos > tot){ if (yi > 1){ sumv += (double)yi * sumi / xi * sum; } return; } if (line[pos][0] < lv) dfs(lv, pos+1, yi, sumi, xi, sum*(line[pos][0]+1)); else{ dfs(lv, pos+1, yi+1, sumi+v[line[pos][lv]], xi, sum*(line[pos][0]-lv+1)); dfs(lv, pos+1, yi, sumi, xi, sum*lv); } } int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) scanf("%d", v+i); memset(head, 1, sizeof(head)); memset(nex, -1, sizeof(nex)); for (int i = 0; i < m; i++){ scanf("%d %d", &x, &y); nex[x] = y; head[y] = 0; } tot = 0; sum = 1.0; sumv = 0; for (int i = 0; i < n; i++) if (head[i]){ line[++tot][0] = 1; line[tot][1] = i; int now = i; int &cnt = line[tot][0]; while (nex[now] != -1){ now = nex[now]; line[tot][++cnt] = now; } } for (int i = 1; i <= tot; i++) sum *= (double)(line[i][0] + 1); for (int i = 1; i <= tot; i++){ int len = line[i][0]; for (int j = 1; j <= len; j++){ int k = line[i][j]; if (tot == 1) sumv += (double)v[k] * (len - j + 1); else sumv += (double)v[k] * sum * (len - j + 1) / (len+1); } } // printf("%.3lf\n", sumv); if (tot > 1){ int maxlv = 1; for (int i = 1; i <= tot; i++) if (line[i][0] > maxlv) maxlv = line[i][0]; for (int i = 1; i <= maxlv; i++){ int xi = 0; for (int j = 1; j <= tot; j++) if (line[j][0] >= i) xi++; dfs(i, 1, 0, 0, xi, 1.0); } } // printf("%.3lf\n", sumv); printf("%.3lf\n", sumv/(sum-1.0)); } return 0; }
HDOJ 4923 Room and Moor
题意:
给定序列Ai,只有0和1,你要选择一个序列Bi,满足单调非递减,每一项范围在[0,1]的条件,使得Σ(Ai - Bi)^2最小。
分析:
先考虑贪心,前面连续的0和末尾连续的1都可以去掉,每当碰上0,不用上升,如果是1,考虑上升和上升的高度,然后就跪了。可以想象最后的Bi应该是一条条高度上升的线段,也就是从l到r的一段区间,Bl..Bi..Br的值相同,对所求式子求导,或是直接展开成一个二次函数,会发现对于一段区间,Bi的最优值等于Ai中对应区间的1的个数除以1和0的个数(即区间长度)。通过这样的方式来贪心处理不了100...000111...110这种情况。其实可以引入单调栈让我们有“反悔”的机会。单调栈里存的是之前的区间的Bi的大小,显然是递增的。我们加入新的区间(开始就是新的点),计算它的Bi最优值,如果比栈顶的高,我们就加入栈。如果比栈顶低,我们就把栈顶区间取出,和当前区间合并,再和新栈顶比较,直到比某个栈顶高或者栈空,将合并后的区间压入栈。最后扫描一遍栈求出答案即可。
#include<cstdio> using namespace std; const int maxn = (int)1e5+10; struct node{ int l, r; double h; node(){} node(int ll, int rr, double hh):l(ll), r(rr), h(hh){} } stack[maxn]; int T, n; int a[maxn], sum[maxn]; int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); sum[0] = 0; for (int i = 1; i <= n; i++){ scanf("%d", a+i); sum[i] = sum[i-1] + a[i]; } int top = 0; for (int i = 1; i <= n; i++){ node now = node(i, i, sum[i]-sum[i-1]); while(top > 0 && now.h < stack[top-1].h){ top --; now.l = stack[top].l; now.h = (double)(sum[now.r] - sum[now.l-1])/(now.r - now.l + 1); } stack[top++] = now; } double ans = 0; for (int i = 0; i < top; i++){ int ll = stack[i].l, rr = stack[i].r; int len = rr - ll + 1; double hh = stack[i].h; int tot = sum[rr] - sum[ll-1]; ans += hh * hh * len - 2.0 * tot * hh + tot; } printf("%.6lf\n", ans); } return 0; }
HDOJ 4925 Apple Tree
题意:
n×m的图,每格可以种苹果或施肥,种苹果得一个苹果,施肥的格子上下左右的格子若种苹果则苹果数翻倍,问最多能得几个苹果。
分析:
本场签到题,观察发现黑白染色可以获得最多的苹果。范围很小,可以直接染色求结果,推公式也很快。(提示:先考虑1×m的情况,再考虑2×m的情况,推广到n×m的情况)
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdlib> #include<set> #include<map> #include<queue> #include<ctime> #include<string> using namespace std; int T; char aa[30], bb[30]; int a[20], b[20]; int abig[10], bbig[10], acnt[10], bcnt[10]; int trans(char x) { if ('3' <= x && x <= '9') return x - '0' - 2; if (x == 'T') return 8; if (x == 'J') return 9; if (x == 'Q') return 10; if (x == 'K') return 11; if (x == 'A') return 12; if (x == '2') return 13; if (x == 'X') return 14; if (x == 'Y') return 15; } bool legal() { memset(acnt, 0, sizeof(acnt)); int sum = 0; for (int i = 1; i <= 15; i++) sum += a[i]; // printf("%d\n", sum); if (sum > 6) return false; if (sum == 1) return true; for (int i = 1; i <= 15; i++){ if (a[i]) acnt[a[i]]++; } // for (int i = 1; i <= 15; i++) // printf("%d ", a[i]); // printf("\n"); // for (int i = 1; i <= 6; i++) // printf("%d ", acnt[i]); // printf("\n"); if (sum == 2 && acnt[2]) return true; if (sum == 3 && acnt[3]) return true; if (sum == 4 && acnt[4]) return true; if (sum == 4 && acnt[3]) return true; if (sum == 5 && acnt[3] && acnt[2]) return true; if (sum == 6 && acnt[4]) return true; return false; } bool comp() { if (legal()) return 1; if (a[14] && a[15]) return 1; if (b[14] && b[15]) return 0; memset(abig, -1, sizeof(abig)); memset(acnt, 0, sizeof(acnt)); memset(bbig, -1, sizeof(bbig)); memset(bcnt, 0, sizeof(bcnt)); for (int i = 1; i <= 15; i++){ if (a[i]){ acnt[a[i]]++; for (int j = 1; j <= a[i]; j++) abig[j] = i; } if (b[i]){ bcnt[b[i]]++; for (int j = 1; j <= b[i]; j++) bbig[j] = i; } } if (abig[4] > bbig[4]) return true; else if (bbig[4] != -1) return false; if (abig[1] > bbig[1]) return true; if (abig[2] > bbig[2]) return true; if (abig[3] > bbig[3]) return true; if (abig[3] != -1 && acnt[1] != 0 && bcnt[1] == 0 && bcnt[2] == 0) return true; if (abig[3] != -1 && acnt[2] != 0 && bcnt[2] == 0) return true; return false; } int main() { scanf("%d", &T); while(T--) { scanf("%s %s", aa, bb); memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for (int i = 0; i < strlen(aa); i++){ int x = trans(aa[i]); a[x] ++; } for (int i = 0; i < strlen(bb); i++){ int x = trans(bb[i]); b[x] ++; } bool win = comp(); if (win) puts("Yes"); else puts("No"); } return 0; }
View Code
相关文章推荐
- 2014 Multi-University Training Contest 8 部分题目解题报告
- 2014 Multi-University Training Contest 1 部分题目解题报告
- 2014 Multi-University Training Contest 2 部分题目解题报告
- 2014 Multi-University Training Contest 7 部分题目解题报告
- 2014 Multi-University Training Contest 9 部分题目解题报告
- 2014 Multi-University Training Contest 10 部分题目解题报告
- 2014 Multi-University Training Contest 解题报告
- 2014 Multi-University Training Contest 2--by 镇海中学 解题报告
- 2015 Multi-University Training Contest 6 solutions BY ZJU(部分解题报告)
- 2014 Multi-University Training Contest 1--by FZU 解题报告 多校解题报告
- 2015 Multi-University Training Contest 6 solutions BY ZJU(部分解题报告)
- 2014 Multi-University Training Contest 2--by 镇海中学 解题报告
- 2010 ACM-ICPC Multi-University Training Contest(12)——Host by WHU 部分题目解题报告
- 2014 Multi-University Training Contest 1--by FZU 解题报告
- 2014 Multi-University Training Contest 2--by 镇海中学 解题报告
- 2014 Multi-University Training Contest 1--by FZU 解题报告
- 2014 Multi-University Training Contest 1--by FZU 解题报告
- 2014 Multi-University Training Contest 2 1011 ZCC Loves Codefires 解题报告
- 2014 Multi-University Training Contest 1--by FZU 解题报告
- 2014 Multi-University Training Contest 2--by 镇海中学 解题报告