Monoxer Programming Contest 2024(AtCoder Beginner Contest 345)(A,B,C,D,E,F)

比赛链接

这场。。。好像已经是一周之前的比赛来着,终于补完了。

C是个披着字符串外衣的数学容斥题。D是个超级超级暴力的爆搜,写起来超级麻烦,感觉。。。真是一次酣畅淋漓的赤石。E是个DP,朴素想法其实比较直观,不过优化起来就很抽象了。F图论dfs跑一下就可以了,意外的简单。

一个我觉得讲的很好的视频讲解A-G(评论区里面有博客链接,放着讲解和代码)


A - Leftrightarrow

题意:

您将得到一个由“<”、“=”和“>”组成的字符串 S S S

判断 S S S 是否为双向箭头字符串。

字符串 S S S 是双向箭头字符串,当且仅当存在正整数 k k k ,使得 S S S 是一个“<”、 k k k “=`s和一个”>"的连接,按此顺序,长度为 ( k + 2 ) (k+2) (k+2)

思路:

判断一下给定字符串是不是第一个是 <,最后一个是 >,中间全是 = 就行了。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

string s;

int main(){
	cin>>s;
	if(s[0]=='<' && s[s.length()-1]=='>' && 
		s.substr(1,s.length()-2).find_first_not_of("=")==string::npos)
		puts("Yes");
	else puts("No");
	return 0;
} 

B - Integer Division Returns

题意:

如果给定一个介于 − 1 0 18 -10^{18} 1018 1 0 18 10^{18} 1018 之间的整数 X X X ,则打印 ⌈ X 10 ⌉ \left\lceil \dfrac{X}{10} \right\rceil 10X

这里, ⌈ a ⌉ \left\lceil a \right\rceil a 表示不小于 a a a 的最小整数。

思路:

C++的整数除法是向零取整,换句话说,对正数是向下取整,对负数是向上取整。

code:

#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;

ll x;

int main(){
	cin>>x;
	if(x<0)cout<<x/10;
	else cout<<(x+9)/10;
	return 0;
}

C - One Time Swap

题意:

您将得到一个字符串 S S S 。查找执行以下操作恰好一次可产生的不同字符串数。

  • N N N S S S 的长度。选择一对整数 ( i , j ) (i,j) (i,j) ,例如 1 ≤ i < j ≤ N 1\leq i \lt j\leq N 1i<jN ,并交换 S S S 的第 i i i 和第 j j j 个字符。

可以证明,在这个问题的约束条件下,你总是可以执行它。

思路:

暴力枚举交换的两个位置,并统计所有不同的串肯定是不行的。考虑怎么样会产生一次不同的串也很麻烦。所以正难则反,考虑怎么交换是会重复的,并用总的交换方式减去重复的即可。

不难发现相同字符交换的话得到的就是原串,这时候是重复的。所以我们统计每种字符出现的次数,用总的选择数减去每种字符从中选两个的选择数即可。

不过需要注意的是,一开始的串并没有算上,所以第一次相同字母交换得到的和原串相同的串也是会产生一次贡献,特判一下即可。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
typedef long long ll;

string s;
map<char,ll> mp;
ll n,ans;

int main(){
	cin>>s;
	for(auto x:s)mp[x]++;
	n=s.length();
	ans=n*(n-1)/2;
	bool flag=false;
	for(auto t:mp){
		ll x=t.second;
		if(!flag && x>1){
			ans+=1;
			flag=true;
		}
		ans-=x*(x-1)/2;
	}
	cout<<ans;
	return 0;
}

D - Tiling

题意:

存在 H H H 行和 W W W 列的网格,每个单元具有 1 1 1 的边长,

我们有 N N N 个瓷砖。

i i i 块( 1 ≤ i ≤ N 1\leq i\leq N 1iN )是一个大小为 A i × B i A_i\times B_i Ai×Bi 的矩形。

确定是否可以将瓷砖放置在网格上,以便满足以下所有条件:

  • 每个单元格都被正好一块瓷砖覆盖。
  • 可以有未使用的瓷砖。
  • 放置时,瓷砖可以旋转或翻转。

但是,每个瓷砖必须与网格的边缘对齐,而不会延伸到网格之外。

思路:

发现 H , W , N H,W,N H,W,N 非常小,考虑直接暴力。

先枚举所有的选取情况,然后对每种选取情况尝试放置在网格上。放某块砖的时候直接暴力枚举每个位置(假设枚举的位置是瓷砖的左上角),然后枚举旋转情况(因为是矩形,旋转两次 90 ° 90\degree 90° 相当于不旋转,翻转相当于没动,因此我们只需要验证不旋转和旋转一次 90 ° 90\degree 90° 即可)

这里可以稍微加个剪枝,就是对一种选取情况,选到的砖的总面积一定等于 H ∗ W H*W HW

code:

看着长,其实逻辑并不复杂,但是不妨碍这是一道粪题。

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

int n,h,w;
pair<int,int> a[15];

bool pick[15];
bool vis[15][15];
bool checkprint(int x,int y,int idx){//检查是否可以放这块瓷砖
	if(x+a[idx].first-1>h || y+a[idx].second-1>w)return false;
	for(int i=x;i<x+a[idx].first;i++)
		for(int j=y;j<y+a[idx].second;j++)
			if(vis[i][j])
				return false;
	return true;
}
void print(int x,int y,int idx,bool st){//放/移除 这块瓷砖
	for(int i=x;i<x+a[idx].first;i++)
		for(int j=y;j<y+a[idx].second;j++)
			vis[i][j]=st;
}
bool checkprint2(int x,int y,int idx){//旋转90°再放
	if(x+a[idx].second-1>h || y+a[idx].first-1>w)return false;
	for(int i=x;i<x+a[idx].second;i++)
		for(int j=y;j<y+a[idx].first;j++)
			if(vis[i][j])
				return false;
	return true;
}
void print2(int x,int y,int idx,bool st){//旋转90°再放
	for(int i=x;i<x+a[idx].second;i++)
		for(int j=y;j<y+a[idx].first;j++)
			vis[i][j]=st;
}
vector<int> tt;
bool dfs2(int idx){//尝试放第idx块瓷砖
	if(idx>=(int)tt.size()){
		return true;
	}
//	cout<<idx<<endl;
	for(int x=1;x<=h;x++){
		for(int y=1;y<=w;y++){
			if(vis[x][y])continue;
			if(checkprint(x,y,tt[idx])){
				print(x,y,tt[idx],1);
				if(dfs2(idx+1))return true;
				print(x,y,tt[idx],0);
			}
			if(a[tt[idx]].first!=a[tt[idx]].second && checkprint2(x,y,tt[idx])){
				print2(x,y,tt[idx],1);
				if(dfs2(idx+1))return true;
				print2(x,y,tt[idx],0);
			}
		}
	}
	return false;
}
bool check(){//剪枝&检查这个旋转情况
	int tot=0;
	for(int i=1;i<=n;i++)
		if(pick[i])
			tot+=a[i].first*a[i].second;
	if(tot!=h*w)return false;
	
	tt.clear();
	for(int i=1;i<=n;i++)
		if(pick[i])
			tt.push_back(i);
	return dfs2(0);
}

void dfs(int idx){//枚举选举情况
	if(idx>n){
		if(check()){
			puts("Yes");
			exit(0);
		}
		return;
	}
	
	pick[idx]=true;
	dfs(idx+1);
	pick[idx]=false;
	dfs(idx+1);
}

int main(){
	cin>>n>>h>>w;
	for(int i=1;i<=n;i++){
		cin>>a[i].first>>a[i].second;
	}
	sort(a+1,a+n+1,[&](pair<int,int> a,pair<int,int> b){return a.first*a.second>b.first*b.second;});
	
	dfs(1);
	puts("No");
	return 0;
}

E - Colorful Subsequence

题意:

N N N 个球排成一排。

左起第 i i i 个球的颜色为 C i C_i Ci ,值为 V i V_i Vi 。Takahashi想要从这一行中删除精确的 K K K 个球,以便在剩余的球的排列中,没有两个相邻的球具有相同的颜色。

高桥希望在不改变顺序的情况下,将这一行中的 K K K 个球移除,这样在排列剩余的球时,就不会有相邻的两个球颜色相同。此外,在此条件下,他希望最大化这一行中剩余球的总价值。

请计算高桥是否能移除 K K K 个球,使剩下的一行中没有相邻的两个球颜色相同。如果可以,求剩余球的最大总值。

思路:

朴素的动态规划思路还是比较好想的。即设 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k] 表示前 i i i 个球删掉 j j j 个,最后一个球的颜色为 k k k 的最大剩余价值。枚举到第 i i i 个球时,可以通过删掉或者不删掉第 i i i 个球来转移,删掉则从 d p [ i − 1 ] [ j − 1 ] [ k ] dp[i-1][j-1][k] dp[i1][j1][k] 转移过来,不删掉则从 d p [ i − 1 ] [ j ] [ k ′ ] dp[i-1][j][k'] dp[i1][j][k] 转移过来( k ′ k' k 表示所有非 c i c_i ci 颜色的颜色)。

不过时间复杂度为 N ∗ K ∗ N N*K*N NKN 的,肯定爆掉了 。发现其实我们不需要知道那么多颜色的答案,因为我们只要保证转移过来时不撞颜色就行,所以要么是从最大价值的颜色转移过来,要么从除了这个颜色以外剩下的最大价值转移过来。因此我们第三维只需要存储最大的价值和颜色,以及除了这个颜色以外的最大的价值和颜色,这样时间复杂度就优化到了 N ∗ K ∗ 2 N*K*2 NK2

不过这时候空间复杂度也为 N ∗ K ∗ 2 N*K*2 NK2,会 M L E MLE MLE。考虑到我们第一维推到第 i i i 个位置的时候,它只和第 i − 1 i-1 i1 个位置的 d p dp dp 值有关,所以我们可以用滚动数组的思想来优化:我们只存储前一个位置和现在要推的位置的 d p dp dp 值即可。

话说得轻巧,但是写起来超级麻烦 ,真是一场畅快淋漓的赤石啊!

如果我们第三位存储两种颜色,即最大价值的颜色和次大价值的颜色,那么我们需要另开一个长度为 2 2 2 的颜色数组来存,然后我们更新答案的时候,就需要考虑到:尝试更新最大价值但是颜色冲突,更新最大价值但是颜色不冲突 ,更新次大价值但是颜色冲突,更新次大价值但是颜色不冲突。然后呢,更新最大价值的时候还要顺便更新次大情况,还要考虑到无解的情况。写到大脑空空,两眼逐渐智慧起来。在这里插入图片描述

然后没办法去借鉴题解了。

题解写法确实好 。我们不把颜色放在第三维度,而是把颜色当作一个信息,与最大价值一起存储起来,把所有可能的信息都存储在 d p dp dp 下。具体来说,设 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示前 i i i 个球删掉 j j j 个的 所有 最大价值和最后一个球的颜色。代码实现如下:

typedef long long ll;
#define pll pair<ll,ll>
const vector<pll> infv={{-inf,-1},{-inf,-2}};
vector<vector<vector<pll> > > dp(2,vector<vector<pll> >(k+1,infv));

这串代码可以理解为一个二维的 v e c t o r vector vector,然后它存储的“值”是 v e c t o r < p l l > vector<pll> vector<pll> p l l pll pll 就是每个状态(最大价值和最后一个球的颜色) , v e c t o r < p l l > vector<pll> vector<pll> 其实就是把所有状态存进了一个 v e c t o r vector vector

这样书写的好处一个是我们可以把每个可能的情况都直接扔进 v e c t o r vector vector 里,而不需要马上讨论更新答案,最后再找 最大价值及颜色和次大价值及颜色。另外一个好处就是我们可以往里面扔两个价值很小且颜色不同的状态来占位置(也就是上面这串代码的 i n f v infv infv),这样就可以不用处理无解或者只有一种颜色的情况——价值小于0就是不符合的情况。

code:

最考C++语法的一集

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define pll pair<ll,ll>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const int maxk=505;
const ll inf=1e18;

int n,k;

int main(){
	cin>>n>>k;
	
	const vector<pll> infv={{-inf,-1},{-inf,-2}};
	vector<vector<vector<pll> > > dp(2,vector<vector<pll> >(k+1,infv));
	dp[0][0][0].first=dp[0][0][1].first=0;
	
	for(int i=1;i<=n;i++){
		ll c,v;
		cin>>c>>v;
		auto &pre=dp[(i-1)&1],&t=dp[i&1];
		for(int j=0;j<=k;j++)t[j]=infv;
		
		for(int j=1;j<=k;j++){//删掉第i个球 
			for(auto &x:pre[j-1]){
				t[j].push_back(x);
			}
		}
		for(int j=0;j<=k;j++){//不删第i个 
			for(auto &x:pre[j]){
				if(x.second!=c){
					t[j].push_back(pll(x.first+v,c));
					break;
				}
			}
		}
		
		for(int j=0;j<=k;j++){
			//排序去重
			sort(t[j].begin(),t[j].end(),greater<pll>());
			for(int k=1;k<t[j].size();k++){
				if(t[j][k].second!=t[j][0].second){
					swap(t[j][k],t[j][1]);
					break;
				}
			} 
			t[j].resize(2);
		}
		
	}
	
	ll ans=dp[n&1][k][0].first;
	if(ans>=0)cout<<ans<<endl;
	else cout<<-1<<endl;
	
	return 0;
}

F - Many Lamps

题意:

有一个简单图,其 N N N 个顶点编号为 1 1 1 N N N M M M 条边编号为 1 1 1 M M M 。边 i i i 连接顶点 u i u_i ui v i v_i vi

每个顶点都有一盏灯。最初,所有的灯都是熄灭的。在 0 0 0 M M M 次(包括 0 0 0 次和 M M M 次)之间执行以下操作,确定是否可以正好打开 K K K 盏灯:

  • 选择一条边。设 u u u v v v 是边的端点。切换 u u u v v v 上的灯的状态。

也就是说,如果灯亮了,就把它关掉,反之亦然。如果可以准确打开 K K K 盏灯,则打印实现此状态的操作序列。

思路:

直接看 上面说的题解 即可,讲的非常严谨了,没我什么事了。

这里提一嘴链式前向星的一个小性质:加入的第 i i i 条边在 e e e 数组中占第 2 ∗ i − 1 , 2 ∗ i 2*i-1,2*i 2i1,2i 的下标,这两条边是正反两个方向的,异或 1 1 1 可以相互切换。

code:

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
const int maxn=2e5+5;

int n,m,k;

int head[maxn],cnt;
struct edge{
	int v,nxt;
}e[maxn<<1];
void add(int u,int v){
	e[++cnt].v=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}

bool vis[maxn],light[maxn];
int tot=0;
vector<int> ans;
void dfs(int u,int fa){
	vis[u]=true;
	for(int i=head[u],v;i;i=e[i].nxt){
		v=e[i].v;
		if(vis[v])continue;
		dfs(v,u);
		if(!light[v] && tot<k){
			light[v]=true;
			if(light[u])light[u]=false;
			else light[u]=true,tot+=2;
			ans.push_back((i+1)>>1);//上面说的链式前向星的存边小性质
		}
	}
}

int main(){
	cin>>n>>m>>k;
	if(k&1){
		cout<<"No";
		return 0;
	}
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	for(int i=1;i<=n;i++)
		if(!vis[i])
			dfs(i,-1);
	
	if(tot==k){
		cout<<"Yes\n"<<ans.size()<<endl;
		for(auto x:ans)
			cout<<x<<" ";
	}
	else cout<<"No";
	
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自媒体用ChatGPT批量洗稿软件V5.9环境配置/软件设置教程【汇总】

大家好&#xff0c;我是淘小白~ 首先&#xff0c;感谢大家的支持~~ ChatGPT采集洗稿软件V5.9版本更新&#xff0c;此次版本更新修改增加了一些内容&#xff1a; 1、自定义多条指令&#xff0c;软件自动判断指令条数&#xff0c;进行输入 2、增加谷歌浏览多账号轮询&#xf…

了解Kafka位移自动提交的秘密:避免常见陷阱的方法

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 了解Kafka位移自动提交的秘密&#xff1a;避免常见陷阱的方法 前言位移自动提交简介自动提交的优缺点自动提交位移的优点&#xff1a;自动提交位移的缺点&#xff1a;自动提交与手动提交的对比分析&am…

vuex - 21年的笔记 - 后续更新

vuex是什么 Vuex是实现组件全局状态&#xff08;数据&#xff09;管理的一种机制&#xff0c;方便的实现组件之间的数据的共享 使用vuex统一管理状态的好处 能够在vuex中集中管理共享的数据&#xff0c;易于开发和后期维护能够高效地实现组件之间的数据共享&#xff0c;提高…

如何系统的入门大模型?

GPT图解&#xff0c;从0到1构建大模型。 本书将以生动活泼的笔触&#xff0c;将枯燥的技术细节化作轻松幽默的故事和缤纷多彩的图画&#xff0c;引领读者穿梭于不同技术的时空&#xff0c;见证自然语言处理技术的传承、演进与蜕变。在这场不断攀登技术新峰的奇妙之旅中&#xf…

数据安全运营:难点突破与构建策略全解析

小型企业关注基础安全运营&#xff0c;重点把安全产品“管好”和“用好”。大型企业通过SOC平台&#xff08;安全运营中心&#xff09;把所有安全产品串联起来&#xff0c;对大量的日志进行关联分析&#xff0c;发现事件和告警。通过SOAR平台把运营工作中能“自动化”内容进行预…

修改Linux系统时间与网络同步

文章目录 1、安装ntpdate2、修改时区3、设置系统时间与网络时间同步4、将系统时间写入硬件时间 1、安装ntpdate # Red Hat和Cent OS系统 sudo yum install ntpdate # 乌班图 sudo apt-get install ntpdate2、修改时区 1&#xff09;运行tzselect tzselect2&#xff09;选择A…

H4012耐压30V降压恒压芯片 30V降12V降5V 支持电流3A

耐压30V降压恒压芯片的工作原理如下&#xff1a; 该芯片内部集成了开关管和同步整流管&#xff0c;通过它们进行电压的转换&#xff0c;将输入的30V电压降至所需的输出电压&#xff08;如12V或5V&#xff09;。在工作过程中&#xff0c;该芯片通过PWM&#xff08;脉冲宽度调制…

一套键盘鼠标控制两台电脑 Mouse Without Borders

有两台电脑&#xff0c;一台笔记本一台台式机&#xff0c;拥有各自拥有鼠标和键盘&#xff0c;但总是需要切换&#xff0c;感觉太麻烦&#xff0c;想找个简单的方式&#xff0c;不需要额外操作就能同时操作这两台电脑。无意间发现了一个微软软件Mouse Without Borders&#xff…

项目起冲突,掌握这个模型的人,赢麻了!

在项目管理中&#xff0c;冲突是项目经理们无法避免的一环。在职场中&#xff0c;大家都是如何解决矛盾冲突的呢&#xff1f; 一、项目起冲突的原因及解决方法 项目管理过程中&#xff0c;冲突的产生&#xff0c;往往源自于多个方面&#xff0c;但无论是出于何种原因的项目冲…

#Linux(连接档概念)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;硬链接&#xff08;inode&#xff0c;建立硬链接的文件inode号相同&#xff09; &#xff08;2&#xff09;创建硬链接:ln 文件名1 文件名…

项目中如何进行限流(限流的算法、实现方法详解)

❤ 作者主页&#xff1a;李奕赫揍小邰的博客 ❀ 个人介绍&#xff1a;大家好&#xff0c;我是李奕赫&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 记得点赞、收藏、评论⭐️⭐️⭐️ &#x1f4e3; 认真学习!!!&#x1f389;&#x1f389; 文章目录 限流的算法漏…

quartz整合前端vue加后端springboot

因工作需求&#xff0c;需要能修改定时的任务&#xff0c;前端vue3&#xff0c;后端是springboot 看看页面效果&#xff1a; 首先maven加上引入 <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><versi…

日常 ------------ (一)

使用xdd 生成 firmware.cc 文件 &#xff0c;然后程序根据需要自己解压缩,也可以完成软件升级状态的监控 objcopy 此等神奇也可以&#xff0c;但是威力太大&#xff0c;容易玩崩&#xff0c;没敢尝试

Solo 开发者周刊 (第8期):Claude公司再度上新产品,成交额将超73亿美元

这里会整合 Solo 社区每周推广内容、产品模块或活动投稿&#xff0c;每周五发布。在这期周刊中&#xff0c;我们将深入探讨开源软件产品的开发旅程&#xff0c;分享来自一线独立开发者的经验和见解。本杂志开源&#xff0c;欢迎投稿。 好文推荐 Claude是否超过Chatgpt,成为生成…

Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证

昨日&#xff0c;Redis 官方宣布了一项重要变更&#xff1a;他们将修改开源协议&#xff0c;未来所有版本将采用 “源代码可用” 的许可证。 具体来说&#xff0c;Redis 不再使用 BSD 3-Clause 开源协议进行分发。从 Redis 7.4 版本开始&#xff0c;Redis 将采用 SSPLv1 和 RSA…

【C语言】自定义类型:联合体和枚举

1. 联合体 1.1 联合体类型的声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成&#xff0c;这些成员可以是不同的类型。 但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫&#xff1a;共用体。 给联合…

Binance labs孵化的Swan Chain明牌空投测试网零撸教程

简介&#xff1a;Swan Chain 是一个 Layer2云计算网络&#xff0c;可以将数据、计算、带宽和支付集成到一个套件&#xff0c;为Web3项目提供全面的解决方案。 相关概念&#xff1a;云计算、layer2、infrastructure 融资信息&#xff1a;项目在去年获得bi’an领投的300万美元融…

【pip安装时出现一大片红色报错】 raise ReadTimeoutError(self._pool, None, “Read timed out.“)

【pip安装时出现一大片红色报错】 raise ReadTimeoutError(self._pool, None, “Read timed out.”) 问题描述&#xff1a;pip 安装包时出现一大片莫名其妙的报错 raise ReadTimeoutError(self._pool, None, “Read timed out.”) pip._vendor.urllib3.exceptions.ReadTimeout…

onConfigurationChanged与 Save-Restore InstanceState机制与RetainNonConfiguration机制

android横竖屏切换的生命周期 没设置configChanges&#xff0c;销毁后重建&#xff1a; onCreate--onStart--onResume--onPause--onStop--onSaveInstanceState--onDestroy--onCreate--onStart--onRestoreInstanceState--onResume--onPause--onStop--onDestroy 设置configCha…

基于 Google MediaPipe 进行人体姿势估计演示

用于人体姿势估计的 MediaPipe 演示 MediaPipe简介 MediaPipe是一个开源框架&#xff0c;用于构建跨平台、多模式应用机器学习管道。它由 Google 开发&#xff0c;旨在促进基于机器学习的功能的快速开发和部署&#xff0c;特别关注音频、视频和时间序列数据。 我可以将 MediaPi…