Codeforces Round #838 (Div. 2) 题解

本文精选了Codeforces平台上的四道题目A、B、C、D的解题思路及代码实现,涵盖数组操作、排序构造、字符串处理及交互式算法等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A 题目链接:Problem - A - Codeforces

input:

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

output:

0
2
1
4

题意:

现给出一个定义:如果一个数组所有元素的和是偶数,则称该数组为 good 。

给定长度为 n 的数组 a ,给定一种操作:任选数组 a 中的一个元素,将其除以2(下取整),问最少操作多少次,可以使数组 a 为 good。

思路:

数组中奇数的个数会影响总和的结果:

1.如果奇数个数为偶,那么不需要任何操作,数组 a 即为 good,直接输出0即可。

2.如果奇数个数为奇,那么需要将奇数个数变为偶。有两种方案,一是令某个奇数变为偶数,二是令某个偶数变为奇数。由于 n 很小,所以说直接遍历数组,维护每个元素奇偶性改变所需要的最小操作次数的最小值即可。

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n;
int a[N];
bool vis[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		int cnt=0;
		
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			vis[i]=0;
			if(a[i]&1)
			{
				cnt++;
				vis[i]=1;
			}
		}
		if(cnt%2==0)
		{
			cout<<0<<endl;
			continue;
		}
		int ans=10000;
		for(int i=1;i<=n;i++)
		{
			int k=0;
			if(vis[i])
			{
				while(a[i]%2==1)
				{
					a[i]/=2;
					++k;
				}
				ans=min(ans,k);
			}
			else
			{
				while(a[i]%2==0)
				{
					a[i]/=2;
					++k;
				}
				ans=min(ans,k);				
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

B 题目链接:Problem - B - Codeforces

input:

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

output:

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 的所有元素对 ai , aj 满足 max(ai , aj) 可以被 min(ai , aj) 整除,则称该数组为 good 。

给定长度为 n 的数组 a ,给定一种操作:任选 a 中的一个元素,令其加上不大于自身的任意自然数 x ,并保证元素修改后的值不大于1e18。试对数组 a 进行修改,使其为 good ,并保证操作次数不大于 n 次。

思路:

直接对数组 a 从小到大排序,以最小元素的两倍为基准,将其后不大于基准值的元素全部构造为基准值,若当前元素已经大于该元素的两倍,将基准值不断乘2,直至基准值大于当前元素,然后构造,依次类推,注意计数并离线处理答案。

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
//#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int mod=1e9+7;
const int N=2e5+10;


int t,n;

struct node{
	ll v;
	int id;
}a[N];

bool cmp(node a,node b)
{
	return a.v<b.v;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].v;
			a[i].id=i;
		}
		sort(a+1,a+n+1,cmp);
		ll cur=a[1].v;
		vector<PII> vec;
		for(int i=2;i<=n;i++)
		{
			while(a[i].v>cur*2)
			{
				cur*=2;
			}
			if(a[i].v<cur*2)
			{
				vec.push_back({a[i].id,cur*2-a[i].v});
			}
			else if(a[i].v==cur*2)
			{
				continue;
			}
		}
		cout<<vec.size()<<endl;
		for(int i=0;i<vec.size();i++)
		{
			cout<<vec[i].first<<" "<<vec[i].second<<endl;
		}
	}
	return 0;
}

C 题目链接:Problem - C - Codeforces

input:

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

output:

1
1
3
3
21
365

题意:

现给出一个定义:对于长度为奇数01串 b ,如果对于每一个奇数位的前缀,都满足该前缀的中位数即为该前缀的最后一位,那么称数组 b 为 good(01串的中位数即为众数)。

对于一个长度为 k 的01串,定义其 extension:长度为 2k - 1 的01串,第 2i - 1 位是原串的第 i 位,构造方式有2^(k-1)种(可以理解为长度k的串,两两字符之间共 k - 1 个空,每个空可以插入0或1)。

给定长度为 n 的01串 s ,试求出该串的所有前缀的所有满足 good 的扩展方案总和(有点绕,大致就是这个意思,如果不能很好理解我的翻译,可以看原题面)。

思路:

明显递推。推了一会儿状态转移,只推出了当前位和前一位相等的状态转移方程,看了一下样例,直接根据样例猜的当前位和前一位不相等的状态转移:

1.当前位和前一位相等,则当前前缀的目标方案数是前一位的前缀的目标方案数的两倍

2.当前位和前一位不等,则当前前缀的目标方案数为1

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int N=2e5+10;

int t,n;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		string s;
		cin>>s;
		s=" "+s;
		int cur=1;
		int ans=1;
		for(int i=2;i<=n;i++)
		{
			if(s[i]!=s[i-1])
			{
				cur=1;
				ans=(ans+1)%mod;
			}
			else
			{
				cur=(cur*2)%mod;
				ans=(ans+cur)%mod;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

D 题目链接:Problem - D - Codeforces

input:

2
2

1

1
5

2

4

1

output:



? 1 2

! 1 2


? 1 2

? 2 3

! 3 3

题意:

交互题。

给定一个数 n ,评测方有一个长度为 n 的排列 p(由 0 ~ n - 1 组成,询问方看不到该排列)。现在可以向评测方提出不超过 2n 次询问,询问格式为:"? i j",评测方会给出一个数,代表 gcd( pi , pj)。所有询问结束后,询问方需提供两个下标,意为数字 0 在两个下标之一上,提供格式为:"! x y"

提供答案结束后,评测放会返回 1 或 -1,询问方须接收这个返回。1代表答案正确,-1代表答案错误,程序返回 wrong answer。

注意:gcd(0 , x) == x (这个很重要!!!)

思路:

某一个非0值与 0 gcd,得到的是该数本身,并且该数与其余任何数的 gcd 都不可能超过该数本身。所以0和其余数 gcd 得到的值是这个数通过 gcd 能得到的值里最大的。因此我们令 x = 1 , y = 2,从下标3开始往后遍历,每次遍历询问两次: x, i 和 y , i,设得到的两个结果分别为 a 和 b 。分以下三种情况讨论:

1. a == b,说明当前 pi 一定不是 0 ,因为0和两个不同的数 gcd 一定是得到不同的值,所以直接跳过,不做任何操作,继续遍历

2. a > b,我们维护 gcd 较大的情况,令 y = i ,继续遍历

3. a < b,意义同上,令 x = i ,继续遍历

遍历结束后提供 x 和 y 即可。

代码如下:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;

int t,n,x,y,a,b;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		x=1,y=2;
		for(int i=3;i<=n;i++)
		{
			cout<<"? "<<x<<" "<<i<<endl;
			cin>>a;
			cout<<"? "<<y<<" "<<i<<endl;
			cin>>b;
			if(a==b)
				continue;
			else if(a>b)
				y=i;
			else 
				x=i;				
		}
		int k;
		cout<<"! "<<x<<" "<<y<<endl;
		cin>>k; 
	}
	return 0;
}

抱歉,根据提供的引用内容,我无法理解你具体想要什么题。请提供更清晰明确的题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【CodeforcesCodeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值