Codeforces Round #838 (Div. 2)

news2024/11/18 0:33:49

A. Divide and Conquer

题目链接:Problem - A - Codeforces

样例输入:

4
4
1 1 1 1
2
7 4
3
1 2 4
1
15

样例输出:

0
2
1
4

题意:一个数组是好的当且仅当所有的元素和是一个偶数,现在给我们一个初始数组,我们可以对这个数组进行操作,每次操作可以选择一个数并将其缩小为原来的一半,注意是下取整,现在问我们至少需要操作多少次才能把给定数组变为好的。

分析:容易发现,一个数组的元素和要么是奇数要么是偶数,如果一开始是偶数的话那么我们呢就没有必要进行操作,否则我们必须要改变一个数的奇偶性才能把数组变为好的,因为任意两个数之间是不会相互影响的,所以我们不需要同时对两个数进行操作,我们只需要遍历一遍所有的数,记录每一个数改变奇偶性所需要的最少操作次数,那么答案就是所有最小操作次数中的最小值。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=53;
int a[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int mi=0x3f3f3f3f;
		int ans=0;
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			ans+=a[i];
			int cnt=1;
			while((a[i]&1)==((a[i]/2)&1)) 
				cnt++,a[i]/=2;
			mi=min(mi,cnt);
		}
		if(ans&1) printf("%d\n",mi);
		else puts("0");
	}
	return 0;
}

B. Make Array Good

题目链接:Problem - B - Codeforces

样例输入: 

4
4
2 3 5 5
2
4 8
5
3 4 343 5 6
3
31 5 17

样例输出:

4
1 2
1 1
2 2
3 0
0
5
1 3
1 4
2 1
5 4
3 7
3
1 29
2 5
3 3

题意:一个数组是好的当且仅当这个数组中的任意两个数a和b都存在整除关系,即a|b或者b|a成立,现在我们需要对数组进行操作,每次操作可以把一个数a加上x,x是一个不大于a的非负整数,现在让我们进行不超过n次的操作使得数组变为好的,输出一种可行方案。

分析:我们可以考虑把所有数都变为2的幂次,这样的话一定有任意两个数之间存在整除关系,而且我们可以发现,对于任意一个数a,都会有一个x是2的幂次且满足a<=x<=2*a,那么我们只需要让a加上x-a即可将a变为大于等于a的第一个2的幂次,这样的操作次数一定是n,满足题意。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=1e5+10;
int a[N],x[N];
vector<int>p;
int main()
{
	int T;
	cin>>T;
	long long t=1;
	while(t<=2e9) p.push_back(t),t<<=1;
	while(T--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			x[i]=*lower_bound(p.begin(),p.end(),a[i])-a[i];
		}
		printf("%d\n",n);
		for(int i=1;i<=n;i++)
			printf("%d %d\n",i,x[i]);
	}
	return 0;
}

C. Binary Strings are Fun

题目链接:Problem - C - Codeforces

样例输入: 

6
1
1
1
0
2
11
3
010
9
101101111
37
1011011111011010000011011111111011111

样例输出:

1
1
3
3
21
365

题意:一个奇数长度的01串b是好串需要满足以下条件:

对于任意一个奇数下标idx:

如果b[idx]=1,那么前idx个位置中1的个数要大于0的个数

如果b[idx]=0,那么前idx个位置中0的个数要大于1的个数。

对于一个长度为k的01串a,扩展后的01串长度就为2*k-1,假设扩展后的01串为c,那么就满足a[i]=c[2*i-1]

现在给定一个长度为n的01串a,求a的扩展串中是好串的数量,对998244353取模。

分析:设f[i]表示前i位扩展后占多数的情况数,g[i]表示前i位扩展后只多一个的方案数

那么我们现在来分析第i位的更新:

初始条件肯定有f[1]=g[1]=1

如果第i位和第i-1位是相同的,那么扩展后我们多出来需要自己填写的那一位可以填1也可以填0,这个时候就有f[i]=f[i]*2,要想保证前i位扩展后占多数的那一位比占少数的那一位只多1,那么需要在前i-1位扩展后占多数的那一位比占少数的那一位只多1的基础上在新扩展的那一位上填上与这一位相反的数字即可,即g[i]=g[i-1].

如果第i位和第i-1位是相反的,那么扩展后我们多出来需要自己填写的那一位一定要填与第i位相同的数字,而且要保证前i-1位扩展的扩展后占多数的那一位比占少数的那一位只多1,这样的话才能够实现前i位扩展后第i位上的数字出现次数多,而且只会多1,所以有f[i]=g[i],而且g[i]=g[i-1].

通过这样我们就能递推出最终的结果了。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=2e5+10,mod=998244353;
int f[N];//f[i]表示前i位扩展后占多数的情况数
int g[N];//g[i]表示前i位扩展后只多一个的方案数 
char s[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		scanf("%d%s",&n,s+1);
		f[1]=g[1]=1;
		int ans=1;
		for(int i=2;i<=n;i++)
		{
			if(s[i]!=s[i-1]) g[i]=g[i-1],f[i]=g[i];
			else f[i]=f[i-1]*2%mod,g[i]=g[i-1];
			ans=(ans+f[i])%mod; 
		}
		printf("%d\n",ans);
	}
	return 0;
}

但是我们发现无论相邻两位是否相同都有g[i]=g[i-1],又因为一开始g[1]=1,那么可以知道所有的g数组都是1,所以我们可以省掉g数组了

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=2e5+10,mod=998244353;
int f[N];//f[i]表示前i位扩展后占多数的情况数
char s[N];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		scanf("%d%s",&n,s+1);
		f[1]=1;
		int ans=1;
		for(int i=2;i<=n;i++)
		{
			if(s[i]!=s[i-1]) f[i]=1;
			else f[i]=f[i-1]*2%mod;
			ans=(ans+f[i])%mod; 
		}
		printf("%d\n",ans);
	}
	return 0;
}

D. GCD Queries

题目链接:Problem - D - Codeforces

样例输入: 

2
2

1

1
5

2

4

1

样例输出:



? 1 2

! 1 2


? 1 2

? 2 3

! 3 3

题意:给定一个长度为n的排列0~n-1,现在让我们找出来0的下标,只需要找出来两个数i,j,只要满足其中一个数是0的下标即可。每次我们可以给出两个不同的下标i和j进行询问,电脑会反馈pi和pj的最大公约数,其中定义0与a的最大公约数就是a。让我们在询问次数不超过2*n的情况下找到满足题目条件的i和j。

分析:我们首先固定一个数,让这个数与其余的n-1个数进行询问,这样我们就可以唯一的确定第一个数的值。

比如说第一次我们固定的数是2,那么我们用2与其余所有数进行询问,那么询问的答案最大就是2,因为任何一个数与2的最大公约数不可能比2还大,所以第一个数就是2,同理可以得到其他数也是一样的。这样我们通过一次操作就可以得到第一个固定的数是2.我们已经知道了其余所有数与2的最大公约数是几了,对于最大公约数不是2的数我们就可以直接排除了,因为0与2的最大公约数是2,所以通过这一次操作我们就将n个数变为了n/2个数,花费了n次(注意这里确切是n-1次操作,不过为了方便书写方便就写n了,由于n>n-1,所以如果n可行那么n-1更可行)操作。下一次我们就至少可以将n/2个数变为n/4个数,花费的操作次数就是n/2,依次类推就有n+n/2+n/4+……<2*n的,所以这个方法是可行的,最后只剩下两个数时直接退出即可

如果我们第一个数是k,那么n次操作就可以将n个数变为n/k个数,那么这样最后花费的次数会更少,所以我们不必担心次数的问题。

但是我们忽略了一个问题,就是当第一个数是1的时候,我们花费了n次操作,结果全部是1,那么我们这n次操作就相当于只排除了第一个数。所以我们需要额外注意一下这种情况,我们让第一个数与第二个数进行一次询问,再让第一个数与第三个数进行一次询问,如果两次答案是一样的话那么说明第一个数不是0,我们直接把第一个数清空即可,如果两次答案不一样虽然不能说明第一个数一定是0,但是可以说明第一个数一定不是1,因为1与任何数询问得到的结果都是相同的,那么根据上面的分析我们可以发现询问次数一定是够用的。我们通过两次操作排除了一个数,就相当于原来问题是在2*n次询问中从n个数中找,现在变为了在(2*n-2)次询问中从n-1个数中找,这是等价的,只是问题规模变小了而已。

代码中是从最后一个数开始往前询问的。

因为每次询问完都会保留第一个数,所以每询问完一轮我都会对所有的数进行一次反转,这样上次固定的数一定会在这次被删除

注意这个细节。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		scanf("%d",&n);
		vector<int>p;
		for(int i=1;i<=n;i++) p.push_back(i);
		int x;
		while(p.size()>2)
		{
			reverse(p.begin(),p.end());
			vector<int> t;
			t.push_back(p[p.size()-1]);
			int mx=0;
			for(int i=0;i<=1;i++)
			{
				printf("? %d %d\n",p[p.size()-1],p[i]);
				fflush(stdout);
				scanf("%d",&x);
				if(x>mx)
				{
					mx=x;
					t.clear();
					t.push_back(p[p.size()-1]);
					t.push_back(p[i]);
				}
				else if(x==mx)
					t.push_back(p[i]);
			}
			if(t.size()==3)//说明最后一个数肯定不是0,主要是用于排除最后一个数是1的情况
			{
				p.pop_back();
				continue;
			}
			for(int i=2;i<p.size()-1;i++)
			{
				printf("? %d %d\n",p[p.size()-1],p[i]);
				fflush(stdout);
				scanf("%d",&x);
				if(x>mx)
				{
					mx=x;
					t.clear();
					t.push_back(p[p.size()-1]);
					t.push_back(p[i]);
				}
				else if(x==mx)
					t.push_back(p[i]);
			}
			p=t;
		}
		printf("! %d %d\n",p[0],p[1]);
		fflush(stdout);
		scanf("%d",&x);
	}
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android---组件化

1、单体应用 所有代码写在一个工程里。不同业务写到各自模块&#xff0c;以包名来区分。 弊端 1、无论包名做的再好&#xff0c;随着项目扩大&#xff0c;项目失去层次感&#xff0c;接受吃力。 2、报名作为约束&#xff0c;太弱了。一不注意就会出现不同业务之间之间相互调…

【算法数据结构专题】「限流算法专项」带你认识常用的限流算法的技术指南(分析篇)

限流 限流的目的是通过对并发访问/请求进行限速&#xff0c;或者对一个时间窗口内的请求进行限速来保护系统&#xff0c;一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理 限流一词常用于计算机网络之中&#xff0c;定义如下&#xff1a; In computer networks, rate l…

接口测试(七)—— 参数化、数据库操作类封、接口自动化框架

目录 一、接口自动化测试框架 1、目录结构 二、封装iHRM登录 1、普通方式实现 2、登录接口对象层 3、登录接口测试用例层 4、封装断言方法 三、参数化 1、回顾UnitTest参数化 1.1 原始案例 1.2 参数化实现 1.3 从json文件读取 2、登录接口参数化 2.1 组织数据文…

java8流操作之不常用但是很好用的隐藏api

前言 1、一些普通的方式就不再多说了&#xff0c;这里主要说一些不常用的&#xff0c;但是作用很大的api方式 2、如果想要细致了解可以参考 JAVA8的流操作&#xff0c;十分推荐 一、flatMap 1、这个api主要是用来推平流的&#xff0c;和map不一致&#xff0c;map是对象到对…

Python基础(十六):函数的初步认识

文章目录 函数的初步认识 一、函数的作用 二、函数的使用步骤 1、定义函数 2、调用函数 3、快速体验 三、函数的参数作用 四、函数的返回值作用 1、应用 五、函数的说明文档 1、语法 2、快速体验 3、函数嵌套调用 七、函数应用 1、打印图形 2、函数计算 八、总…

还在为多张Excel汇总统计发愁?Python 秒处理真香!

为什么越来越多的非程序员白领都开始学习 Python &#xff1f;他们可能并不是想要学习 Python 去爬取一些网站从而获得酷酷的成就感&#xff0c;而是工作中遇到好多数据分析处理的问题&#xff0c;用 Python 就可以简单高效地解决。本文就通过一个实际的例子来给大家展示一下 P…

新手传奇gm架设要学会的几个修改技巧

每个传奇gm对于架设一个服务器都有自己独立的看法和想法&#xff0c;一些人之所以会想着要架设一个传奇私服主要原因是自己在其他人的服力玩得不是那么舒心。所以想要按照自己的想法和思路打造一个适合自己的专属服务器进行游戏&#xff0c;其实这两者之间是有必然联系的&#…

毕业三年活得像个废物,转行网络安全,写给像我一样迷茫的人...

首先说说我吧&#xff0c;普通二本非科班商贸专业毕业&#xff0c;三年了&#xff0c;做过电商&#xff0c;做过新媒体&#xff0c;做过业务员&#xff0c;从躺平到摆烂&#xff0c;一开始还挺享受这样的生活的&#xff0c;毕竟每月4千工资&#xff0c;抛出吃住&#xff0c;剩个…

重学webpack系列(八) -- webpack的运行机制与工作原理

前面几个章节我们分别去探索了webpack的loader机制、plugin机制、devServer、sourceMap、HMR&#xff0c;但是你是否知道这些配置项是怎么去跟webpack本身执行机制挂钩的呢&#xff1f;这一章我们就来探索一下webpack的运行机制与工作原理吧。 webpack核心工作过程 我们打开w…

第十四章 文件操作

1.文件的基本操作 文件&#xff0c;对我们并不陌生&#xff0c;文件是数据源&#xff08;保存数据的地方&#xff09;的一种&#xff0c;比如大家经常使用的Word文档&#xff0c;TXT文件&#xff0c;excel文件…都是文件。文件最主要的作用就是保存数据&#xff0c;它既可以保…

用户虚拟地址空间管理-mm_struct

一、进程虚拟地址空间管理概览 二、mm_struct结构体的主要成员 atomic_t mm_users;共享同一个用户虚拟地址空间的进程的数量&#xff0c;也就是线程组包含的进程的数量atomic_t mm_count;内存描述符的引用计数struct vm_area_struct *mmap;虚拟内存区域链表struct rb_root mm_…

【java】课程设计--抽卡模拟器

文章目录工期安排自己实现菜单逻辑抽卡算法0.书写要求1.用户需求2.设计思想3.各个功能和算法描述4.系统调试中问题5.总结新知识怎么打开任务管理器改进&#xff08;进一步的设想&#xff09;交给她们实现1.注册登录2.读文件-显示查找内容暂时成功案例工期安排 1 自定义增加和删…

数据权限就该这么设计

在项目实际开发中我们不光要控制一个用户能访问哪些资源&#xff0c;还需要控制用户只能访问资源中的某部分数据。 控制一个用户能访问哪些资源我们有很成熟的权限管理模型即RBAC&#xff0c;但是控制用户只能访问某部分资源&#xff08;即我们常说的数据权限&#xff09;使用…

[附源码]Python计算机毕业设计红旗家具城管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

✿✿✿JavaScript --- 事件

目录 1.事件相关概念 2. js中注册监听&#xff08;事件绑定&#xff09;的方式 (1)在定义标签时&#xff0c;添加事件名称属性。属性值是js代码&#xff08;js代码会被自动封装到一个function函数的方法体中&#xff09; (2)通过js获取元素对象&#xff0c;再添加事件。 补…

ADI Blackfin DSP处理器-BF533的开发详解54:CVBS输出-DSP和CH7024的应用详解(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 CVBS OUT 视频输出 硬件实现原理 CVBS_OUT 子卡板连接在 ADSP-EDU-BF53x 开发板的扩展端口 PORT3 和 PORT4 上&#xff0c;板卡插入时&#xff0…

window10 下Tomcat安装步骤

目录先安装JDK根据JDK选择tomcat版本下载安装设置系统变量运行测试先安装JDK 略过 根据JDK选择tomcat版本 打开CMD窗口&#xff0c;运行java -version查看本机JDK版本 C:\Users\admin>java -version java version "11.0.17" 2022-10-18 LTS Java(TM) SE Runtime E…

python函数讲解进阶

关于python函数的基本知识可以点击“python函数讲解” 目录 一.函数多返回值 思考 二.函数参数种类 1.位置参数 2.关键字参数 3.缺省参数 4.不定长参数 位置传递 关键字传递 总结 三.匿名函数 函数作为参数传递 lambda匿名函数 一.函数多返回值 思考 运行之后&…

Python抓取电商平台数据 / 采集商品评论 / 可视化展示 词云图...

前言 大家早好、午好、晚好吖 ❤ ~ 我给大家准备了一些资料&#xff0c;包括: 2022最新Python视频教程、Python电子书10个G &#xff08;涵盖基础、爬虫、数据分析、web开发、机器学习、人工智能、面试题&#xff09;、Python学习路线图等等 直接在文末名片自取即可&#x…

[附源码]Node.js计算机毕业设计公交电子站牌管理系统软件Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…