Codeforces Round #537 (Div. 2) 题解报告

A. Superhero Transformation

题意

问能否通过把辅音字母换成另一个辅音字母,元音字母换成另一个元音字母使得两个字符串相同。

题解

按题意模拟。

代码

#include<bits/stdc++.h>
const int N = 1e3 + 10;
int ri() {char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f  = -1;for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
char s[N], t[N]; int n, m;
bool ok[N];
int main() {ok['a'] = true;ok['e'] = true;ok['i'] = true;ok['o'] = true;ok['u'] = true;scanf("%s", &s); int n = strlen(s);scanf("%s", &t); int m = strlen(t);if(n != m) return puts("No"), 0;for(int i = 0;i < n; ++i)if(ok[s[i]] != ok[t[i]]) return puts("No"), 0;puts("Yes");return 0;
}

B. Average Superhero Gang Power

题意

给一个序列,你可以操作mmm次,每次可以去掉某个数或者将某个数+1,后者每个数不能做超过kkk次。最大化平均值。

题解

FST差评,pretest实在太弱,和我一样。
考试的是时候随便贪心了一下,大概就是先一直删然后再大分类,结果发现自己zz了。
实际上枚举删除几个数,贪心地删掉小的那些即可。

代码

#include<bits/stdc++.h>
const int N = 1e5 + 10;
int ri() {char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f  = -1;for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int n, k, m, a[N];
long long sum, mx;
int main() {n = ri(); k = ri(); m = ri();for(int i = 1;i <= n; ++i)a[i] = ri(), sum += a[i];std::sort(a + 1, a + n + 1);double mx = 0;for(int i = 0;i <= std::min(n - 1, m); ++i) {sum -= a[i];mx = std::max(mx, (double)(sum + std::min((long long)m - i, 1LL * k * (n - i))) / (double)(n - i));}printf("%.10lf\n", mx);return 0;
}

C. Creative Snap

题意

给一个长度为2n2^n2n的基地,在a1⋯aka_1\cdots a_ka1​⋯ak​位置有“复仇者”,你要烧掉整个基地,每次你要么分成两半分别烧,要么直接烧。如果直接烧,没人的话花费AAA,有人的话花费B⋅na⋅lB\cdot n_a \cdot lB⋅na​⋅l,nan_ana​是人数,lll是长度。A,BA,BA,B是给定的常数,问最小花费。

题解

如果nnn小一点的花可以直接分治对吧。
某段ppp的代价f(p)f(p)f(p)就是f(p)=min⁡{f(ls)+f(rs),[cnt[p]=0]⋅A+[cnt[p]≠0]⋅B⋅cnt[p]⋅l}f(p)=\min \{f(ls) +f(rs),[cnt[p]= 0]\cdot A + [cnt[p]\neq0]\cdot B\cdot cnt[p] \cdot l\}f(p)=min{f(ls)+f(rs),[cnt[p]=0]⋅A+[cnt[p]̸​=0]⋅B⋅cnt[p]⋅l},cnt[p]cnt[p]cnt[p]是人数ls,rsls,rsls,rs是左右子区间。
然后把整个分治结构看成一颗线段树,那么计算f(p)f(p)f(p)相当于是在用左右子树更新当前子树。
动态开点即可。

代码

#include<bits/stdc++.h>
const int M = 31e5 + 10;
int ri() {char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f  = -1;for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int cnt[M], ls[M], rs[M], A, B, n, k, sz, rt;
long long f[M];
void Ins(int &p, int L, int R, int x) {if(!p) p = ++sz; ++cnt[p];if(L == R) return f[p] = 1LL * B * cnt[p], void();int m = L + R >> 1;if(x <= m) Ins(ls[p], L, m, x);else Ins(rs[p], m + 1, R, x);f[p] = std::min(1LL * B * cnt[p] * (R - L + 1), f[ls[p]] + f[rs[p]]);
}
int main() {n = ri(); k = ri(); A = ri(); B = ri();f[0] = A; int all = 1 << n;for(int i = 1;i <= k; ++i)Ins(rt, 1, all, ri());printf("%lld\n", f[rt]);return 0;
}

D. Destroy the Colony

题意

有一个由大写字母和小写字母组成的长度为偶数一个字符串,将这个字符串重排列,使得重排列以后把字符串劈成两半,任何相同的字符都同一半的位置上,同时满足原字符串xxx和yyy两种字符也在同一半上。多组询问。

题解

这题差一点点想出来了。如果不是T2FSTT2FSTT2FST,T4T4T4没想出来的话,我现在可能已经橙了TT。
显然本质不同的询问只有C522=1326C_{52}^2=1326C522​=1326种。
考虑如果我们已经决定了每种字符归属哪边,那么方案数就是将两边重排列的方案数的乘积,也就是
(n2)!∏cnt1[i]⋅(n2)!∏cnt2[i]=((n2)!)2∏cnt[i]\frac{(\frac{n}{2})!}{\prod cnt_1[i]} \cdot \frac{(\frac{n}{2})!}{\prod cnt_2[i]}=\frac{((\frac{n}{2})!)^2}{\prod cnt[i]}∏cnt1​[i](2n​)!​⋅∏cnt2​[i](2n​)!​=∏cnt[i]((2n​)!)2​
其中必须满足∑cnt1[i]=n2\sum cnt_1[i]=\frac{n}{2}∑cnt1​[i]=2n​
暴力枚举每种询问,合并两种字符,现在问题就转化成了给定若干个数,选择几个数使得他们的和是n2\frac{n}{2}2n​的方案数。
这显然是一个背包,但是如果暴力做就是O(52C522n2)O(52C_{52}^2\frac{n}{2})O(52C522​2n​)过不去。
一种很显然的思路就是先计算总的答案,然后利用总的答案删去两个数来吧那个O(52)O(52)O(52)给优化掉。
我想到这里就GG了T_T
因为我不会背包删除,然后就开始各种浪,什么多项式求逆之类的都考虑过。
结果发现是自己抽了,考虑删去一个数之前的答案fff和删去一个数之后的答案hhh,那么实际上就是要把fff的方案中选择了当前这个数xxx的方案去掉,所以有hi=fi−hi−xh_i=f_i-h_{i-x}hi​=fi​−hi−x​
然后这题就结束了。

代码

#include<bits/stdc++.h>
const int P = 1e9 + 7, N = 1e5 + 10;
int cnt[N], f[N], g[N], nw[N], h[N], tp[N], ans[52][52], q; char s[N];
int ri() {char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f  = -1;for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int fixu(int x) {return x >= P ? x - P : x;}
int add(int a, int b) {return a += b, fixu(a);}
int fix(int x) {return (x >> 31 & P) + x;}
int mul(int a, int b) {return 1LL * a * b % P;}
int Pow(int x, int k) {int r = 1;for(;k; x = mul(x, x), k >>= 1)if(k & 1)r = mul(r, x);return r;
}
void Up(int &a, int b) {a = mul(a, b);}
int Id(char c) {return 'a' <= c && c <= 'z' ? c - 'a' : c - 'A' + 26;}
int main() {scanf("%s", s + 1); int n = strlen(s + 1) >> 1;f[0] = 1;for(int i = 1;i <= n; ++i)f[i] = mul(f[i - 1], i);g[n] = Pow(f[n], P - 2);for(int i = n;i; --i)g[i - 1] = mul(g[i], i);int mx = 0;for(int i = 1;i <= n << 1; ++i)++cnt[Id(s[i])];int all = 1;for(int i = 0;i < 52; ++i)if(cnt[i]) {if(cnt[i] > n) {q = ri();for(int i = 1;i <= q; ++i)puts("0");return 0;}Up(all, g[cnt[i]]);}Up(all, mul(f[n], f[n]));h[0] = 1;for(int i = 0;i < 52; ++i)if(cnt[i])for(int j = n;j >= cnt[i]; --j)h[j] = add(h[j], h[j - cnt[i]]);for(int a = 0;a < 52; ++a) if(cnt[a]) {for(int i = 0;i <= n; ++i)nw[i] = h[i];for(int i = cnt[a];i <= n; ++i)nw[i] = fix(nw[i] - nw[i - cnt[a]]);ans[a][a] = fixu(mul(nw[n], all) << 1);for(int b = 0; b < a; ++b)if(cnt[b]) {for(int i = 0;i <= n; ++i)tp[i] = nw[i];for(int i = cnt[b];i <= n; ++i)tp[i] = fix(tp[i] - tp[i - cnt[b]]);ans[a][b] = ans[b][a] = fixu(mul(tp[n], all) << 1);}}q = ri();for(int i = 1;i <= q; ++i) {int a = ri(), b = ri();printf("%d\n", ans[Id(s[a])][Id(s[b])]);}return 0;
}

E. Tree

题意

给你一棵树,每次指定若干个节点和一个根,你要把他们划分成mmm组,使得每一组内都不存在互为祖先的两个点,求方案数。

题解

考虑新划分一组和塞到原来的某一组。
fi,j=fi−1,j⋅(j−h)+fi−1,j−1f_{i,j}=f_{i-1,j}\cdot(j-h)+f_{i-1,j-1}fi,j​=fi−1,j​⋅(j−h)+fi−1,j−1​
hhh表示a1⋯ai−1a_1\cdots a_{i-1}a1​⋯ai−1​中是aia_iai​的祖先的点数。
我们发现复杂度的瓶颈在于求hhh
考虑不换根。那么我们可以按照Dfs序排序来Dp。这样的话每个点的hhh就是这个点的在a1⋯aka_1\cdots a_ka1​⋯ak​中的祖先数量(因为Dfs序小的才能是它的祖先)。
对于一个点aaa,他会对他的子树内的所有点的hhh产生111的贡献,这个东西可以用一个树状数组来求。
现在复杂度的瓶颈变成了换根。硬核一点的话应该是可以直接上虚树。不过比较麻烦。实际上有一个跟巧妙的做法。
想以1为跟,得到hhh,现在考虑以rrr为根。本质上就是求xxx到rrr的路径上有多少个点是被选中的。所以hnewx=hx+hr−hlca(x,r)+[lca(x,r)∈A]−1hnew_x=h_x+h_r-h_{lca(x,r)}+[lca(x,r)\in A]-1hnewx​=hx​+hr​−hlca(x,r)​+[lca(x,r)∈A]−1,减一是扣掉自己。
然后就可以愉快地Dp啦。

代码

#include<bits/stdc++.h>
const int N = 2e5 + 10, P = 1e9 + 7;
int ri() {char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f  = -1;for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int a[N], to[N], nx[N], pr[N], de[N];
int sz[N], ds[N], fa[N], in[N], out[N], d[N], t[N], h[N], f[301], n, tp, tot;
bool mk[N];
void add(int u, int v) {to[++tp] = v; nx[tp] = pr[u]; pr[u] = tp;}
void adds(int u, int v) {add(u, v); add(v, u);}
void Dfs1(int u, int fa) {::fa[u] = fa; de[u] = de[fa] + 1; sz[u] = 1;for(int i = pr[u]; i;i = nx[i])if(to[i] != fa) {Dfs1(to[i], u);sz[u] += sz[to[i]];if(sz[ds[u]] < sz[to[i]]) ds[u] = to[i];}
}
void Dfs2(int u, int c) {d[u] = c; in[u] = ++tot; if(!ds[u]) return out[u] = tot, void(); Dfs2(ds[u], c);for(int i = pr[u]; i;i = nx[i])if(to[i] != fa[u] && to[i] != ds[u])Dfs2(to[i], to[i]);out[u] = tot;
}
int Lca(int u, int v) {for(;d[u] != d[v]; u = fa[d[u]])if(de[d[u]] < de[d[v]])std::swap(u, v);return de[u] < de[v] ? u : v;
}
void Add(int x, int y) {for(;x <= n; x += x&-x) t[x] += y;}
int Que(int x, int r = 0) {for(;x; x -= x&-x) r += t[x]; return r;}
int main() {n = ri(); int q = ri();for(int i = 1;i < n; ++i)adds(ri(), ri());Dfs1(1, 0); Dfs2(1, 1);for(;q--;) {int k = ri(), m = ri(), r = ri();for(int i = 1;i <= k; ++i)a[i] = ri(), Add(in[a[i]], 1), Add(out[a[i]] + 1, -1), mk[a[i]] = true;int dr = Que(in[r]);for(int i = 1, c;i <= k; ++i)c = Lca(a[i], r), h[i] = Que(in[a[i]]) + dr - (Que(in[c]) << 1) + mk[c] - 1;std::sort(h + 1, h + k + 1);for(int i = 1;i <= k; ++i) //restoreAdd(in[a[i]], -1), Add(out[a[i]] + 1, 1), mk[a[i]] = false;bool flag = true;for(int i = 1;i <= k; ++i)if(h[i] >= m){flag = false; break;}if(!flag) {puts("0"); continue;}f[0] = 1;for(int i = 1;i <= k; ++i)for(int j = std::min(m, i); ~j; --j)f[j] = j <= h[i] ? 0 : (1LL * f[j] * (j - h[i]) + f[j - 1]) % P;long long ans = 0;for(int i = 1;i <= m; ++i)ans += f[i];printf("%lld\n", ans % P);for(int i = 1;i <= m; ++i) //restoref[i] = 0;}return 0;
}

CodeCraft-19 and Codeforces Round #537 (Div. 2)解题报告相关推荐

  1. Codeforces Round #702 (Div. 3)解题报告

    Codeforces Round #702 (Div. 3) 全部题解 读错题意,写了半天真是心态爆炸,总的来看这次题目不难的. A. Dense Array http://codeforces.co ...

  2. Codeforces Round #264 (Div. 2) 解题报告

    Source:  http://codeforces.com/contest/463 打得比较差..第三题想写nlgn的,结果调了很久又wa,以为写挫,过了很久发现做法有问题..最后两题惨淡收场.第四 ...

  3. Codeforces Round #219 (Div. 2) 解题报告

    Problem A Collecting Beats is Fun 题意:就是音乐游戏在4*4的网上一些格子需要在固定的时间点,告诉你一只手同一时间能点几个.问你能不能通关(就是一个不丢) 思路:水题 ...

  4. Codeforces Round #535 (Div. 3) 解题报告

    CF1108A. Two distinct points 做法:模拟 如果两者左端点重合就第二条的左端点++就好,然后输出左端点 #include <bits/stdc++.h> usin ...

  5. CodeCraft-19 and Codeforces Round #537 (Div. 2) Editorial

    CodeCraft-19 and Codeforces Round #537 (Div. 2) Editorial A 不说了 代码 #include<bits/stdc++.h> usi ...

  6. CodeCraft-19 and Codeforces Round #537 (Div. 2)

    A. Superhero Transformation 水题,注意两个字符串可能长度不相等. #include<bits/stdc++.h> #define clr(a,b) memset ...

  7. Codeforces Round #578 (Div. 2) 题解报告

    A. Hotelier sb模拟,直接按题意模拟就可以了. B. Block Adventure Gildong is playing a video game called Block Advent ...

  8. BestCoder Round #77 (div.2)解题报告

    昨晚和Yveh合作的成果-- T1 传送门 题意:给一个正整数集合,求集合中各个子集里各元素的总异或 思路:对于一个数x对自己异或的结果,异或偶数次是x,奇数次为0,而且一个集合的非空子集数目为2n− ...

  9. 构造 Codeforces Round #302 (Div. 2) B Sea and Islands

    题目传送门 1 /* 2 题意:在n^n的海洋里是否有k块陆地 3 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 4 输出完k个L后,之后全部输出S:) 5 5 10 的例子可以 ...

最新文章

  1. linux操作系统教学,Linux操作系统教学视频
  2. 第二周作业-停车场门禁控制系统的状态机
  3. Selenium之定位元素常用的8种方法整理(第一篇)
  4. PowerDesigner 小工具窗
  5. 性能测试总结(二)---测试流程篇
  6. Spring Cloud Gateway之负载均衡
  7. Postgres 数据库安装、配置、备份还原及存储过程
  8. Reset Password 重置密码 (CentOS 5,6,7 ; Juniper Networks: SRX100 )
  9. java碰到乱码如何解决方法_如何处理java的乱码
  10. VB 自启动建立右键菜单
  11. jQuery的立即调用表达式
  12. 《CCNA学习指南:Cisco网络设备互连(ICND1)(第4版)》——2.11节生产网络模拟问题2-1...
  13. 开源工业物联网数据库 Apache IoTDB 毕业成为 Apache 顶级项目!
  14. Dijkstra算法结合时间窗规划无冲突路径
  15. GZHU18级寒假训练:Aquarius's Trial F
  16. 使用EggJS开发接口(三)登录验证之egg-jwt 及 crypto加密
  17. SpringCloud之GateWay的基础使用
  18. 项目经理到底要不要考取PMP证书呢?
  19. RMAN-20005: target database name is ambiguous
  20. wifidog 源码初分析(三)

热门文章

  1. n模块切换node版本
  2. 用python编写神经网络_用Python实现神经网络(第5周)的代价函数
  3. continue 、break的用法
  4. 论数字化转型:转什么,如何转?
  5. (转载) loss不降低原因以及解决方法
  6. 拼多多api商品详情数据接口货品采集
  7. 递归与分治 | 2:最接近点对问题 —— 例题:套圈
  8. Android开发:gradle配置
  9. Java的开源文字识别Tess4j与Tesseract-OCR
  10. 数字化浪潮下,消费金融公司的金融科技之路