Atcoder Beginner Contest 380 题解 (A-G)

news/2024/11/20 1:15:21/文章来源:https://www.cnblogs.com/showball/p/18555940

Atcoder Beginner Contest 380 题解 (A-G)

题目链接

A - 123233

#include<bits/stdc++.h>using namespace std;using i64=long long;void Showball(){string s;cin>>s;sort(s.begin(),s.end());if(s=="122333") cout<<"Yes\n";else cout<<"No\n"; 
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

B - Hurdle Parsing

#include<bits/stdc++.h>using namespace std;using i64=long long;void Showball(){string s;cin>>s;int cnt=0;for(auto c:s){if(c=='|'){if(cnt) cout<<cnt<<" ";cnt=0;}else{cnt++;}} 
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

C - Move Segment

模拟乱搞,下标,边界有点烦。

#include<bits/stdc++.h>using namespace std;using i64=long long;void Showball(){int n,k;cin>>n>>k;string s;cin>>s;vector<int> a,b;string order="";for(int i=0,j=0;i<n;){while(j<n&&s[i]==s[j]) j++;order+=s[i];if(s[i]=='1') a.push_back(j-i);else b.push_back(j-i);i=j;} int one=0,zero=0;a[k-2]+=a[k-1];for(auto c:order){if(c=='1'){if(one==k-1) {one++;continue;}for(int i=0;i<a[one];i++) cout<<1;one++;}else{for(int i=0;i<b[zero];i++) cout<<0;zero++;}}
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

D - Strange Mirroring 思维

经典性质,以 \(01\) 串举例。\(0 \rightarrow 01 \rightarrow0110\rightarrow01101001\)

\(0\) \(1\) \(1\) \(0\) \(1\) \(0\) \(0\) \(1\)

\(0\) \(1\) \(2\) \(3\) \(4\) \(5\) \(6\) \(7\)

我们发现性质:如果当前位 \(i\)\(popcount\), 即 \(2\) 进制下 \(1\) 的个数是奇数,那么该位为 \(1\),否则为 \(0\)

不妨令原串为 \(s\), 大小写反转后的串为 \(t\)。那么我们可以根据这个性质判断当前位落在哪个串中,然后

取模求位置即可。

#include<bits/stdc++.h>using namespace std;using i64=long long;void Showball(){string s,t;cin>>s;int n=s.size();t=s;for(int i=0;i<n;i++){if(islower(t[i])) t[i]=char(t[i]-32);else t[i]=char(t[i]+32);}int q;cin>>q;while(q--){i64 x;cin>>x;x--;i64 p=x/n;int r=x%n;if(__builtin_popcountll(p)&1) cout<<t[r]<<" ";else cout<<s[r]<<" ";}}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

E - 1D Bucket Tool 并查集

可以用并查集来进行维护相同的颜色。只需要维护出这段颜色的左端点以及区间长度即可。

对于查询 \(2\) ,直接查询 \(cnt\) 数组即可。考虑查询 \(1\) 。我们通过并查集的 \(find\) 函数查到 \(x\) 所在区间的左端点。

然后原本区间颜色数量减去区间长度大小。更新颜色,并且维护新颜色的数量。注意还需要判断左右相邻区间颜色是否相同,然后维护颜色并查集即可。

#include<bits/stdc++.h>using namespace std;using i64=long long;struct DSU{vector<int> p, sz;DSU(int n) : p(n + 1), sz(n + 1, 1){ iota(p.begin(), p.end(), 0); }int find(int x){return p[x] == x ? x : p[x] = find(p[x]);}bool same(int x, int y) { return find(x) == find(y); }bool merge(int x, int y){x = find(x), y = find(y);if (x == y) return false;if (x > y) swap(x, y);sz[x] += sz[y];p[y] = x;return true;}};void Showball(){int n,q;cin>>n>>q;DSU dsu(n+1);vector<int> cnt(n+2,1),color(n+2);iota(color.begin(),color.end(),0);while(q--){int op;cin>>op;if(op==1){int x,c;cin>>x>>c;int l=dsu.find(x);int len=dsu.sz[l];cnt[color[l]]-=len;color[l]=c;cnt[color[l]]+=len;if(color[dsu.find(l-1)]==color[l]) dsu.merge(l-1,l);if(color[dsu.find(l+len)]==color[l]) dsu.merge(l,l+len);}else{int c;cin>>c;cout<<cnt[c]<<"\n";}}
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

F - Exchange Game 博弈+状压

我们发现数据范围很小,考虑状态压缩。分别存储先手和后手以及桌上的牌型。

然后记忆化搜索即可。如果一个状态的后继状态中存在一个必败态,那么这个状态一定是必胜态。(因为玩家很聪明,一定会走到这个状态),否则当前状态为必败态。

具体实现参考代码及注释。

#include<bits/stdc++.h>using namespace std;using i64=long long;void Showball(){int n,m,l;cin>>n>>m>>l;int len=n+m+l;vector<int> a(len);for(int i=0;i<len;i++) cin>>a[i];vector<vector<int>> dp(4100,vector<int>(4100));function<int(int,int)> dfs=[&](int x,int y){if(dp[x][y]) return dp[x][y];int st=x+y;for(int i=0;i<len;i++){//枚举桌上牌型if(st>>i&1) continue;for(int j=0;j<len;j++){//枚举当前先手牌型if(!(x>>j&1)) continue;if(a[j]>a[i]){//可以摸桌上牌int t=x-(1<<j)+(1<<i);int tt=dfs(y,t);if(tt==2) return dp[x][y]=1;}else{//不能摸桌上牌int t=x-(1<<j);int tt=dfs(y,t);if(tt==2) return dp[x][y]=1;}}}return dp[x][y]=2;};int x=0,y=0;for(int i=0;i<n;i++) x|=1<<i;for(int i=n;i<n+m;i++) y|=1<<i;int ans=dfs(x,y);cout<<(ans==1?"Takahashi\n":"Aoki\n");
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

G - Another Shuffle Window 思维+期望+逆序对

先来一道前置例题:CF749E

简要题意:给出一个 \(1∼n\) 的排列,从中等概率的选取一个连续段,设其长度为 \(l\) 。对连续段重新进行等概率的全排列,求排列后整个原序列的逆序对的期望个数。

思路:考虑每一对 \((i,j)\) 对答案的贡献。先求出更改前的逆序对数量。再考虑更改后的。不妨设 \(i<j\)

那么如果 \(a_i>a_j\), 那么如果选择的区间包含 \((i,j)\) 就会有 \(\frac{1}{2}\)负贡献。因为从逆序对变成了顺序对。

反之,产生了 \(\frac{1}{2}\)正贡献。区间包含 \((i,j)\) 的概率为:\(\frac{2\times (n-j+1)\times i}{n\times (n+1)}\) 。因此贡献为:\(\frac{(n-j+1)\times i}{n\times (n+1)}\)

我们只需要枚举区间右端点,然后用树状数组统计大于和小于右端点的下标之和即可算出贡献。

统计逆序对使用树状数组即可。

代码

#include<bits/stdc++.h>using namespace std;using i64=long long;void Showball(){int n;cin>>n;vector<int> a(n+1);for(int i=1;i<=n;i++) cin>>a[i];vector<array<i64,2>> tr(n+1);  auto add=[&](int op,int x,int v){for(;x<=n;x+=x&-x) tr[x][op]+=v;};auto getsum=[&](int op,int x){i64 ret=0;for(;x;x-=x&-x) ret+=tr[x][op];return ret;};double q,ans=0;for(int i=1;i<=n;i++){q+=getsum(0,n)-getsum(0,a[i]);add(0,a[i],1);ans-=(n-i+1)*(getsum(1,n)-getsum(1,a[i]));ans+=(n-i+1)*(getsum(1,a[i]));add(1,a[i],i);}ans/=n;ans/=(n+1);cout<<fixed<<setprecision(9)<<q+ans<<"\n";
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

通过上面这个题,我们就会知道长度为 \(n\) 的排列的期望逆序对数为 \(\frac{1}{2}\times C_n^2\)

那么我们去分别考虑每一个长度为 \(k\) 的区间。不妨把序列分成三段 \([1,i-1],[i,i+k-1],[i+k,n]\)

我们发现洗牌中间序列,对三段之间互相形成的逆序对不会有影响。那么我们可以通过算出总的逆序对数和中间段的逆序对数,作差来得到两边区间的逆序对数。除以 \(n-k+1\) 即可。再加上中间区间的 期望逆序对数量

前一部分,我们直接使用树状数组类似滑动窗口的维护即可, 中间区间的期望逆序对数量 就可以用上一题的启发了。即为 \(\frac{k\times (k-1)}{4}\)

#include<bits/stdc++.h>using namespace std;using i64=long long;const int mod = 998244353;void Showball(){int n,k;cin>>n>>k;vector<int> a(n+1);for(int i=1;i<=n;i++) cin>>a[i];vector<i64> tr(n+1);auto add=[&](int x,int v){for(;x<=n;x+=x&-x) tr[x]+=v;};auto getsum=[&](int x){i64 ret=0;for(;x;x-=x&-x) ret+=tr[x];return ret;};auto inv=[&](i64 a){i64 b=mod-2,ret=1;while(b){if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;}return ret;};i64 sum=0;for(int i=n;i;i--){sum+=getsum(a[i]);add(a[i],1);} for(int i=0;i<=n;i++) tr[i]=0;i64 cur=0;for(int i=k;i;i--){cur+=getsum(a[i]);add(a[i],1);}i64 ans=sum-cur;for(int i=1;i+k<=n;i++){add(a[i],-1);cur-=getsum(a[i]);cur+=getsum(n)-getsum(a[i+k]);add(a[i+k],1);ans=(ans+sum-cur)%mod;}ans=(ans*inv(n-k+1)%mod+1LL*k*(k-1)%mod*inv(4)%mod)%mod;cout<<ans<<"\n";
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int t=1;//cin>>t;while(t--){Showball();}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/837100.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 学习笔记(一)-Redis 安装

一、Redis简介 (1)什么是Redis ​ Redis 是完全开源免费的,遵守BSD协议,是一个高性能(NOSQL)的key-value数据库,Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。在企业开发中, 主要用于做数据库、缓…

交互式备忘单: 汇集了各种有用的安全工具

这份工具包是一个交互式备忘单,汇集了各种有用的安全工具,主要用于渗透测试或红队练习。这些工具来自于Github仓库和其他公开来源。以下是工具列表及其分类: AD:用于Active Directory安全的工具。 BinaryExp:用于二进制漏洞利用/入侵的工具。 Blue:用于蓝队操作和防御的工…

29. 使用MySQL之数据库维护

1. 备份数据 像所有数据一样,MySQL的数据也必须经常备份。由于MySQL数据库是基于磁盘的文件,普通的备份系统和例程就能备份MySQL的数据。但是,由于这些文件总是处于打开和使用状态,普通的文件副本备份不一定总是有效。 下面列出这个问题的可能解决方案。使用命令行实用程序…

QT实现组合键监测

QT实现快捷键监测,完成某些组合键功能参考于:Qt 获取组合键 键盘按住某键 鼠标组合实现 - Andy5020 - 博客园MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);QWidget::installEventFilter(this); }bool MainW…

GitLab快速上手指南上篇

作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 目录一.gitlab的基本配置1 登录gitlab并配置汉化2 修改管理员密码3 修改头像4 关闭账号注册功能5 修改邮箱地址二.gitlab用户,组,项目管理1.用户,组,项目查看2.用户管理2.1 新建用户2.2 用户创建成功2.3 …

【springboot开发】Spring Boot3.3 内部配置与外部配置的差异及其应用

在 Spring Boot 开发中,配置管理是关键的组成部分。配置不仅影响应用程序的行为,还直接关系到应用的灵活性和可维护性。Spring Boot 提供了多种方式来管理配置,其中包括内部配置和外部配置。这两种配置方式各有其优势和应用场景,了解它们的特点和使用场景有助于在开发过程中…

DCL

创建用户通过create user 来创建用户 create user 用户名;(不带密码) create user 用户名 identified by 密码;登录用户发现他可以访问的表少,权限比较少; exit 可以退出登录 用户授权 用grant all|权限1,权限2..on 数据库.表 to 用户(with grant option)【加了括号中命…

【springboot开发】Spring Boot 配置文件高级用法

一、总体优先级顺序二、应用配置文件的详细优先级三、文件类型优先级四、特定环境配置五、配置文件高级用法六、案例: 多配置文件处理方式Spring Boot配置文件的优先级是一个重要的概念,它决定了当存在多个配置文件时,哪个配置文件中的配置将被优先采用。 一、总体优先级顺序…

【微服务】微服务中token鉴权设计的4种方式总结

一、JWT鉴权1.1 概述1.2 实现步骤1.2.1 用户登录1.2.2 存储JWT 1.2.3 请求携带JWT1.2.4 服务端验证JWT 1.3 优点 二、OAuth 2.0鉴权2.1 概述2.2 实现步骤2.2.1 授权服务器2.2.2 资源服务器 2.2.3 客户端 2.3 优点三、统一授权中心(API Gateway)3.1 概述3.2 实现步骤 3.2.1 部…

【架构】一文搞懂多规格商品、组合商品模型设计

今天聊聊多规格商品、组合商品模型设计。 一、多规格商品 1.1 什么是多规格商品 多规格商品是指同一款商品具有多个不同的规格或属性,例如颜色、尺寸、材质、容量等。这些规格使得商品能够满足不同消费者的偏好和需求。在新零售系统中,多规格商品通常会以一个商品条目展示,消…

【架构】多租户系统的核心概念模型

让我们深入探讨一下多租户系统的概念模型。概念模型是多租户系统的"骨架",帮助我们理解系统各部分的组织和运作方式。 多租户的核心概念模型 • 租户:通常指一个企业客户,不同租户之间的数据和行为是相互隔离的。• 用户:某个租户内的具体使用者,使用账号、密码…

WinForm 设计器中DPI感知错误解决方法

这张图是WinForm在1080P分辨率下开发的一个Form,但是代码到高分辨率屏幕就会变成这个鸟样虽然说可以通过DPI感知让程序在运行的时候显示出正确的样式,但是这样让我们在设计的时候很是苦恼 在翻看了WinForm微软官方在Net8的更新,发现了这样的一条:我们在项目csproj里面加入一…