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\),对原式变形一下
由此我们可以发现,只需要构造出\(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<<' ';
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧