AtCoder Grand Contest 016做题记录
来源:互联网 发布:python 交易 行情平台 编辑:程序博客网 时间:2024/05/19 10:55
比赛的时候去打CodeM了
赛后补得题目
模拟赛的题还没改完,所以做的比较慢
感觉题目质量还是一如既往的高
A - Shrinking
题意:
对字符串s进行一次变换的规则如下:
- 长度为n的字符串s变换成为长度为n-1的字符串t,对于变换后的t的每一位,都有
ti =si 或si−1
给定字符串s,求将其变成由一个字母组成的字符串的最少步数
解答:
预处理每一位向右离它最近的26个字母的分别的位置
爆枚最后存在的那一个字母,扫一遍字符串判断最早什么时候被该字符覆盖或者被删除。
时空复杂度:
#include <bits/stdc++.h>#define N 1005using namespace std;char s[N];int n,R[N][30];int main() { scanf("%s",s+1); n = strlen(s+1); for (int _=n;_>=1;_--) { for (int i=1;i<=26;i++) R[_][i] = R[_+1][i]; R[_][s[_]-'a'+1] = _; } int ans = 2147483647; for (int _=1;_<=26;_++) { int cur = -1; for (int i=1;i<=n;i++) { int t = n-i+1; if (R[i][_]) t = min(t, R[i][_] - i); cur = max(cur, t); } ans = min(ans, cur); } cout << ans << endl; return 0;}
B - Colorful Hats
题意:
有N只戴帽子的猫,每只猫看不到自己的帽子颜色,但是能看得见别的猫的帽子颜色。现在第i只猫告诉你它看到了
解答:
令总帽子颜色数为T,对于每一只猫,若它的帽子颜色唯一则他所看到的颜色数为T-1,否则为T,我们称帽子颜色的唯一的猫是孤独的。
故若
下面对最大值和最小值的差进行分类讨论:
- 若max=min,那么此时每只猫帽子的颜色为T或者T-1。如果每只猫的帽子的颜色都是T-1,则每只猫都是孤独的,此时T=n-1,否则每只猫所看到的帽子的颜色都是T,由于不存在孤独的猫,所以T至多为
⌊n2⌋ 。综上所述,当max=min时,T=n−1 或T≤⌊n2⌋ - 若max=min+1,此时我们可以统计孤独的猫的个数x,类似上面的推论,颜色数至少为x+1,至多为x+(n-x)/2。故当max=min+1时,
x+1≤T≤x+n−x2
时空复杂度:
#include <bits/stdc++.h>using namespace std;inline int rd() { int x=0,f=1;char ch=getchar(); while (ch>'9'||ch<'0') {if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f;}int n,a[1000500];int main() { n = rd(); for (int _=1;_<=n;_++) a[_] = rd(); int x = a[1], y = a[1]; for (int _=1;_<=n;_++) x = max(a[_], x), y = min(a[_], y); if (x-y > 1) return puts("No"), 0; if (x == y) { if (x == n-1 || x<=n/2) puts("Yes"); else puts("No"); } else { int tot = 0, sum = 0; for (int _=1;_<=n;_++) if (a[_] == y) tot++; //alone for (int _=1;_<=n;_++) if (a[_] == x) sum++; //not alone if (tot+1 <= x && x <= tot + sum/2) puts("Yes"); else puts("No"); } return 0;}
C - +/- Rectangle
题意:
给出H,W,h,w,构造一个由
- 所有元素的和为整数
- 任意一个h*w的子矩阵的和为负数
解答:
显然当h|H且w|W时,显然无解。证明方法即将整个矩阵分解成为若干个h*w的小矩阵的和。
否则,一定存在解。若x%h==0&&y%w==0
时空复杂度:
#include <bits/stdc++.h>#define N 1050#define INF 100000000using namespace std;int n,m,a,b,sum,mp[N][N];inline int rd() {int r;scanf("%d",&r);return r;}int main() { n = rd(), m = rd(), a = rd(), b = rd(); int p1 = INF / (n*m), p2 = -((a*b-1)*p1 + 1); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (i%a == 0 && j%b == 0) mp[i][j] = p2; else mp[i][j] = p1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) sum += mp[i][j]; if (sum <= 0) puts("No"); else { puts("Yes"); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) printf("%d%c",mp[i][j],j==m?'\n':' '); } return 0;}
D - XOR Replace
题意:
给定长度为N的数列A,B,需要将你用若干次操作使得数列A变成数列B。每次操作的内容是取A所有数的异或和x,然后将A的某一位替换成x。询问是否能将A变成B,若能请输出最小步数。
解答:
这题还是想了蛮久的,结论很多要一步一步推出来。
令
那我们不妨将最开始的x看成
问题转化为对
故当构成A数列元素多重集不等于构成B数列的多重集时,无解。
建图:边
故解决
综上所述,在建图之后,判处掉无解和
#include <bits/stdc++.h>#define N 1000500using namespace std;int a[N],b[N],c[N],d[N],fa[N],n,ans,tot;map<int,int> mp;int gf(int x) {return fa[x]==x ? x : fa[x] = gf(fa[x]);}inline int rd() {int r;scanf("%d",&r);return r;}int main() { n = rd(); for (int _=1;_<=n;_++) a[_] = rd(); for (int _=1;_<=n;_++) b[_] = rd(); for (int _=1;_<=n;_++) a[n+1] ^= a[_], b[n+1] ^= b[_]; ++n; for (int _=1;_<=n;_++) c[_] = a[_], d[_] = b[_]; sort(c+1,c+n+1); sort(d+1,d+n+1); for (int _=1;_<=n;_++) if (d[_]!=c[_]) return puts("-1"), 0; for (int _=1;_<=n;_++) if (a[_] != b[_] || _ == n) { _<n ? ++ans :0; !mp[ a[_] ] ? mp[ a[_] ] = ++tot :0; !mp[ b[_] ] ? mp[ b[_] ] = ++tot :0; } if (!ans) return puts("0"), 0; for (int _=1;_<=tot;_++) fa[_] = _; for (int _=1;_<n;_++) if (a[_] != b[_]) fa[ gf( mp[a[_]] ) ] = gf( mp[b[_]] ); for (int _=1;_<=tot;_++) ans += fa[_] == _; cout << ans-1 << endl; return 0;}
时空复杂度:
其中反阿克曼函数来自于并查集,log来自于STLmap
E - Poor Turkeys
题意:
有
- 若
Ai 和Bi 都还没被吃掉,选一只吃掉 - 若
Ai 和Bi 都被吃掉了,则忽略这一次操作 - 若
Ai 和Bi 只有一只还没被吃掉,则吃掉这一只
求在操作后有多少对(x,y)火鸡有可能还存活
解答:
操作的时间顺序会影响答案,这是一个很重要的性质,这可以帮助我们否决掉很多图论相关的做法。
考虑时光倒流,即从最后一次操作开始考虑。
考虑火鸡
- 若操作
At 和Bt 都不是x ,那么显然该操作与火鸡x 存活的情况无关 - 不妨令
At=x ,若在操作后火鸡x 存活,那么在第t 轮前Bt 存活,并且我们选择在这一轮吃掉它。此时与x 一样,它在前t 轮不能被吃掉,加入我们所需要“强制存活”的集合。 - 若
At 和Bt 均为我们要“强制存活”的对象,那么不存在任何一种方案能够使火鸡x 活到最后,因为At 和Bt 中我们必须选一只吃掉
这样从时刻
代码很简单,先枚举一只火鸡
时间复杂度
#include <bits/stdc++.h>#define N 405#define M 100050using namespace std;int F[N][N],imp[N],a[M],b[M],n,m;inline int rd() {int r;scanf("%d",&r);return r; }int main() { n = rd(), m = rd(); for (int _=1;_<=m;_++) a[_] = rd(), b[_] = rd(); for (int x=1;x<=n;x++) { F[x][x] = 1; for (int _=m;_>=1;_--) { if (!F[x][a[_]] && !F[x][b[_]]) continue; if (F[x][ a[_] ] && F[x][ b[_] ]) {imp[x] = 1; break;} if (F[x][ a[_] ]) F[x][ b[_] ] = 1; else F[x][ a[_] ] = 1; } } int ans = 0; for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) if (!imp[i] && !imp[j]) { int flag = 1; for (int _=1;_<=n;_++) if (F[i][_] && F[j][_]) flag = 0; ans += flag; } cout << ans << endl; return 0;}
F - Games on DAG
题意:
给定一个N个点M条边的,无重边的有向无环图,点按照拓扑序编号,求原图
解答:
补集转化,即求sg1=sg2的子图个数,最后用
做法是状态压缩动态规划,
一个有向无环图G,我们可以将它分解成为入度为0的点和入度非0的点,对于入度为非0的点的导出子图G’,在加上入度为0的点后这个点集内的所有点的SG值会+1
这样我们就可以转移了,将
- 集合A中不能有任何连边。若u,v都是入度为0的点集A中的点,那么这条边一定不能存在。(否则v的入度至少为1)
- 对于集合B中的每一个点,它至少向集合A中的点连了一条边(否则该点度数为0,不属于B集合)
- 集合A中的点连向集合B中的点的边可以任意选或者不选
- 集合B中的边的方案数为
FB
通过枚举子集转移,预处理出点
时间复杂度
#include <bits/stdc++.h>#define N 17#define MASK 70000#define mod 1000000007using namespace std;int n,m,tp,sum;int g[MASK][N], F[MASK],e[N*N];inline int lowbit(int x) {return x&(-x);}inline int rd() {int r;scanf("%d",&r);return r;}inline void inc(int &x,int y) {x=(x+y)%mod;}int main() { n = rd(), m = rd(), tp = (1<<n) - 1; e[0] = 1; for (int _=1;_<=m;_++) e[_] = 1LL * e[_-1] * 2 % mod; sum = e[m]; for (int _=1;_<=m;_++) { int a = rd(), b = rd(); g[1<<(b-1)][a] = 1; } for (int _=1;_<=tp;_++) for (int i=1;i<=n;i++) { int x = lowbit(_); g[_][i] = g[_^x][i] + g[x][i]; } F[0] = 1; for (int i=1;i<=tp;i++) if ((i&1) == ((i>>1)&1)){ for (int k=i;k;k=(k-1)&i) if ((k&1) == ((k>>1)&1)){ int j = i^k, cur = F[j], tmp = 1; for (int x=1;x<=n;x++) if ((1<<(x-1))&i) { if ((1<<(x-1)) & j) tmp = 1LL * tmp * (e[g[k][x]]-1) % mod; else tmp = 1LL * tmp * e[g[j][x]] % mod; } inc(F[i], 1LL * cur * tmp % mod); } } int ans = (sum - F[tp]) % mod; ans < 0 ? ans += mod : 0; cout << ans << endl; return 0;}
- AtCoder Grand Contest 016做题记录
- AtCoder Grand Contest 014做题记录
- AtCoder Grand Contest 017做题记录
- AtCoder Grand Contest 018 做题记录
- Atcoder Grand Contest 016F
- 【题解】AtCoder Grand Contest 016
- AtCoder Grand Contest 010
- AtCoder Grand Contest 011
- AtCoder Grand Contest 018
- AtCoder Grand Contest 018
- Atcoder Grand Contest 019
- AtCoder Grand Contest 010
- AtCoder Grand Contest 008
- Atcoder 刷题记录
- Atcoder Grand Contest 011E
- Atcoder Grand Contest 011F
- AtCoder Grand Contest 012 B
- AtCoder Grand Contest 012 A
- jsp内置对象application
- 网文作者的三道坎
- 陀螺仪控制摄像头脚本 GyroController
- 5分钟创建一个SpringBoot + Themeleaf的HelloWord应用
- 栈的顺序存储
- AtCoder Grand Contest 016做题记录
- JAVA基础(一)
- Servlet——解决全站乱码问题(过滤器)
- 最小二乘法与梯度下降法
- Maven配置与项目构建
- 安卓怎么让网页在webview打开
- ubuntu 16.04内核源码编译
- EL隐藏对象
- Bash脚本条件判断和控制流结构