NIYAXIMEN

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  13 随笔 :: 0 文章 :: 0 评论 :: 238 阅读

Educational Codeforces Round 157 (Rated for Div. 2)

Problem - A - Codeforces

构造

签到题没啥好说的

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef pair<int,int>pii;
void solve()
{
	int x,y,k;cin>>x>>y>>k;
	if(x>=y)cout<<x<<endl;
	else
	{
		int r=min(y,x+k);
		cout<<y+y-r<<endl;
	}
}
int main()
{
	int t;cin>>t;
	while(t--)solve();
}

Problem - B - Codeforces

贪心 排序

\(2n\)个数,分为两组,使得每组的相邻两数之差的绝对值相加之和最好

猜一下是将原数组排序后前\(n\)个数字为一组,后\(n\)个数字为一组

可以简单证明一下,设原数组\(a\leq b\leq c \leq d\),那么答案就是\(b-a+d-c\)

然后可以将\(ad\)交换一下,答案就变成了\(d-b+c-a\)

将两者做差得到\(2*(b-c)\leq 0\),前者较小

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N];
typedef pair<int,int>pii;
void solve()
{
	int n;cin>>n;
	for(int i=1;i<=2*n;i++)scanf("%d",&a[i]);
	sort(a+1,a+1+2*n);
	int ans=0;
	for(int i=n;i>1;i--)ans=ans+a[i]-a[i-1];
	for(int i=2*n;i>n+1;i--)ans=ans+a[i]-a[i-1];
	cout<<ans<<endl;
	for(int i=1;i<=n;i++)cout<<a[i]<<' '<<a[i+n]<<endl;
}
int main()
{
	int t;cin>>t;
	while(t--)solve();
}

Problem - C - Codeforces

哈希映射 构造 组合

定义一个好组合为:

长度为偶数且字符串前一半的数位和等于后一半的数位和

给出一系列字符串,找出\((i,j)\)使得\(s_i+s_j\)符合条件,\(i==j\)也合法,\((i,j)(j,i)\)不一样

观察题意发现一个字符串有用的部分只有它的长度和总和,用一个数组来存储就好了

定义\(dp[i][j]\)为长度为\(i\),总和为\(j\)的字符串的个数

然后开始遍历,遍历到\(s_i\)时,假设\(s_i=59736\)

先找可以接在它右边的,由于要求长度是偶数,接在它后面的长度可以为\(1,3,5\),再计算数位和就好了

左边同理

关键在于重复的问题了,我们发现这种做法只能与长度小于等于自身的字符串拼接

如长度为\(3\)的串就在计算的时候不可能和长度为\(5\)的字符串拼接

那么可以发现,一个字符串如果和长度不等于自身的字符串拼接是不会产生重复的

和长度相同的拼接则会有重复,这里可以用\(cnt,same\)分别存储

注意每次\(same\)要减去二,(自己和自己拼接的情况),最后加上\(n\)即可

最后答案就是\(cnt+same/2+n\)


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int dp[7][500];
string s[N];
int ss[N];
void solve()
{
	int n;cin>>n;long long cnt=0,same=0;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		int sum=0,p=s[i].length();
		for(int j=0;j<p;j++)
		{
			sum+=(s[i][j]-'0');
		}
		dp[p][sum]++;
		ss[i]=sum;
	}
	for(int i=1;i<=n;i++)
	{
		string now=s[i];
		int u=now.length();
		now=' '+now;int sum=0;
		if(u%2)
		{
			int f=1;
			for(int j=1;j<=u;j++)
			{
				sum=sum+now[j]-'0';
				if((u+f)/2==j)
				{
					if(u!=f)cnt+=dp[f][sum*2-ss[i]];
					else same+=dp[f][sum*2-ss[i]];
					f+=2;
				}
			}
			f=1;sum=0;
			for(int j=u;j;j--)
			{
				sum=sum+now[j]-'0';
				if((u+f)/2==u-j+1)
				{
					if(u!=f)cnt+=dp[f][sum*2-ss[i]];
					else same+=dp[f][sum*2-ss[i]];
					f+=2;
				}
			}
		}
		else
		{
			int f=2;
			for(int j=1;j<=u;j++)
			{
				sum=sum+now[j]-'0';
				if((u+f)/2==j)
				{
					if(u!=f)cnt+=dp[f][sum*2-ss[i]];
					else same+=dp[f][sum*2-ss[i]];
					f+=2;
				}
			}
			f=2;sum=0;
			for(int j=u;j;j--)
			{
				sum=sum+now[j]-'0';
				if((u+f)/2==u-j+1)
				{
				    if(u!=f)cnt+=dp[f][sum*2-ss[i]];
					else same+=dp[f][sum*2-ss[i]];
					f+=2;
				}
			}
		}
		same-=2;
		//cout<<cnt<<' '<<same<<endl;
	}
	cout<<cnt+same/2+n<<endl;
}
int main()
{
	int t;t=1;
	while(t--)solve();
}

Problem - D - Codeforces

Trie字符串 位运算 构造 异或和

给出\(n-1\)个数字\(a-1,a_2...a_{n-1}\)

定义\(a_i=b_i\oplus b_{i+1}\)

构造出\(n\)\(b_i\)且还要满足\(0\leq b_i \leq n-1,b_i!=b_j\)

由于\(b_i \oplus b_i=0\),对原式变形一下

\[a_1=b_1\oplus b_2,b_2=a_1\oplus b_1\\ a_2=b_2\oplus b_3,b_3=a_2\oplus b_2=a_1 \oplus a_2 \oplus b_1\\ s_i=a_1\oplus a_2 \oplus a_3...\oplus a_{i}\\ b_i=s_{i-1}\oplus b_1 \]

由此我们可以发现,只需要构造出\(b_1\)就行了,题目保证一定有解,所以\(s_i\)不会出现两个零,满足了第二个条件

对于第一个条件,首先大于等于\(0\)是必然的,只需要让\(max(s_{i-1}\oplus b_1)\leq n-1\)即可

我们可以从\(0\)\(n-1\)枚举\(b_1\)(正序倒序一样的),而对于求\(max\)可以用\(Trie\)\(lgn\)的时间内完成

对于\(Trie\)字典树可以参考835. Trie字符串统计 - AcWing题库AcWing 143. 最大异或对 - AcWing

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int tr[2][N*20],idx;
int a[N];
int n,s;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++)
	{
		scanf("%d",&a[i]);
		s=s^a[i];
		int p=0;
		for(int j=20;j>=0;j--)
		{
			int now=(s>>j)&1;
			if(tr[now][p]==0)tr[now][p]=++idx;
			p=tr[now][p];
		}
	}
	int b=0;
	for(int i=0;i<=n-1;i++)
	{
		int res=0,p=0;
		for(int j=20;j>=0;j--)
		{
			int now=(i>>j)&1;
			if(tr[!now][p])
			{
				res=res*2+1;
				p=tr[!now][p];
			}
			else
			{
				res=res*2;
				p=tr[now][p];
			}
		}
		if(res<=n-1)
		{
			b=i;break;
		}
	}
	cout<<b<<' ';
	for(int i=1;i<=n-1;i++)
	{
		b=b^a[i];cout<<b<<' ';
	}
}
posted on   AsukaAlice  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示