Codeforces Round #829-1754A+B与1753A+B+C 题解
1754A - Technical Support
题意
给定一个只包含大写字母 和 的字符串,如果字符串里的每一个 都能与在其之后的 一一对应地匹配,则输出字符串 ,否则输出字符串 。注意,可以有 没有被匹配,但每个 必须成功地匹配。
题解
倒着扫一遍,看某一个 后面的 的数量是否大于 的数量即可,有一个不满足就说明不可以,全部满足就可以
Code
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n;
char a[N];
inline void Main()
{
cin>>n;
cin>>(a+1);
int cnt=0;
for(int i=n;i;--i)
{
if(a[i]=='A')++cnt;
else
{
if(cnt>0)--cnt;
else return puts("No"),void(0);
}
}
puts("Yes");
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int T;
cin>>T;
while(T--)Main();
return 0;
}
1754B - Kevin and Permutation
题意
给定 到 的序列,你需要构造一种排列这 个数的方式使得任意两个相邻的数的差的绝对值的最小值最大,形式化地说,你需要最大化 ,请给出任意一种构造方式
题解
打个表不难发现 的最大值就是
证明也不难,假设最大值是 ,首先序列中一定会出现这个元素,那这个元素和它相邻的元素的差的绝对值一定至少有一个小于等于
若 是偶数,直接 这样排列就可以了
若 是奇数,把 放在最开始,后面的和偶数一样排列就行,像这样:
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1006;
int n,dis;
inline void Main()
{
cin>>n;
if(n&1)cout<<n<<' ';
dis=n>>1;
for(int i=dis;i;--i) cout<<i<<' '<<i+dis<<' ';
cout<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int T=1;
cin>>T;
while(T--)Main();
return 0;
}
1753A - Make Nonzero Sum
题意
给定一个长度为 的序列,仅由 组成(简单版题目仅由 组成),你需要将这个序列分割为若干段
对于一段 来说, 表示这一段中的元素交替加减(第一个元素为加)得到的答案,例如 这一段的
假设一共有 段,你需要保证
请给出任意一种划分方法,若不存在这样的划分方法,输出 -1
题解
考虑对于某一个元素,不同的划分方法只会改变它对于最终答案的贡献的正负,并不会改变贡献的奇偶性,所以说若所有元素的和为奇数,那么就一定无解
再看序列中的元素仅有
由我们上面得到的结论,可以发现在这种情况下一定一共有偶数个元素,考虑对于相邻的两个元素若为 或 ,这两个分为一组即可,若为 或 就分开,单个元素作为一组,这两个区间的贡献加起来也为 ,这样最后的序列一定满足题意
再看困难版本,也就是序列中的元素有
其实与简单版差别并不大,我们还是把相邻的两个不为 的数先分为一组(一定一共有偶数个非零的数字),固定左边界,右边界不断往右扩展,直到找到第二个不为 的数字,现在我们只需要想办法让这个区间的贡献为 即可
先计算这个区间的贡献,若贡献已经为 那就直接使用这个区间,下面考虑贡献不为 时
这个区间最右边的元素一定非 ,若这个区间长度为偶数,那最后一个元素计算贡献的时候就会取反,把最后一个元素单独拿出来作为一段,这样就一定能和前面的区间的答案抵消,整个区间的贡献就是 了
若区间长度为奇数,我们再分类一下,若区间的第一个元素非 ,就直接把它单独作为一段,后面部分的贡献就会取反,这样就一定能和前面的区间的答案抵消,整个区间的贡献也是
若区间长度为奇数,同时区间的第一个元素为 ,就把这个 单独作为一段,后面的按照区间长度为偶数的方法处理即可
Code
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,sum,lst1,a[N];
vector<pair<int,int>>ans;
void Main()
{
cin>>n;
lst1=sum=0;
for(int i=1;i<=n;++i)cin>>a[i],sum+=a[i];
if(sum&1)return cout<<"-1\n",void(0);
ans.clear();
for(int i=1,lst=1,f1=-1;i<=n;++i)
{
if(a[i]==0)continue;
lst1=i;
if(f1==-1){f1=i;continue;}
if((((f1-lst+1)&1)?a[f1]:-a[f1])+(((i-lst+1)&1)?a[i]:-a[i])==0)
{
ans.emplace_back(make_pair(lst,i));
lst=i+1;
f1=-1;
continue;
}
if((~(i-lst+1))&1)
{
ans.emplace_back(make_pair(lst,i-1));
ans.emplace_back(make_pair(i,i));
lst=i+1;
f1=-1;
continue;
}
if((i-lst+1)&1)
{
if(a[lst])
{
ans.emplace_back(make_pair(lst,lst));
ans.emplace_back(make_pair(lst+1,i));
lst=i+1;
f1=-1;
continue;
}
else
{
ans.emplace_back(make_pair(lst,lst));
++lst;
--i;
continue;
}
}
}
if(lst1!=n)ans.emplace_back(lst1+1,n);
cout<<ans.size()<<'\n';
for(auto x:ans)cout<<x.first<<' '<<x.second<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int T=1;
cin>>T;
while(T--)Main();
return 0;
}
1753B - Factorial Divisibility
题意
给定两个正整数 和 和一个正整数序列 ,询问 是否能被 整除
题解
显然 ,于是乎我们把 装进桶里,从小到大枚举,只要能进位就进位,让 的阶乘数量加上就好
假设这样进位完毕之后最小的阶乘为 ,只要 就说明可以整除,否则不行
Code
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+1;
int n,x,mn;
int a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>x;
for(int i=1,tmp;i<=n;++i)cin>>tmp,++a[tmp];
for(int i=1;i<=N;++i)
{
a[i+1]+=a[i]/(i+1);
a[i]%=(i+1);
if(a[i])
{
mn=i;
break;
}
}
puts(mn<x?"No":"Yes");
return 0;
}
1753C - Wish I Knew How to Sort
题意
给出一个 01 序列,每次操作会随机选择两个数交换,求期望要多少次操作才能使整个序列单调不降(答案对于 取模)
题解
假设一共有 个 1,显然最终的序列最后 个都是 1,假设现在最后 个数中有 个 1 和 个 0,那么前面的 个数中就一定有 个 1
要希望整个序列单调不降,那就是要把前 个数中的 1 和后 个数中的 0 交换,这样的交换一共有 种换法,总共的换法为 ,所以成功让后 个数中多出一个 1 的概率就是
期望操作次数就是 ,然后 就会增加 ,直到 增加到 就满足条件了
假设最后 个数中一开始有 个 1 最终的答案就是
Code
// LUOGU_RID: 91311868
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,mod=998244353;
int n,cnt,k,all,ans;
int a[N];
inline void Mul(int &x,int y){ll z=1ll*x*y;if(z>=mod)z%=mod;x=z;}
inline int mul(int x,int y){ll z=1ll*x*y;if(z>=mod)z%=mod;return z;}
inline void Add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
inline int add(int x,int y){x+=y;if(x>=mod)x-=mod;return x;}
inline int fp(int x,int p)
{
int ans=1;
for(;p;p>>=1,Mul(x,x))if(p&1)Mul(ans,x);
return ans;
}
inline int inv(int x){return fp(x,mod-2);}
void Main()
{
cin>>n;
all=mul(mul(n,n-1),inv(2));
k=ans=cnt=0;
for(int i=1;i<=n;++i)cin>>a[i],cnt+=a[i];
for(int i=n-cnt+1;i<=n;++i)k+=a[i];
for(;k<=cnt;++k)Add(ans,mul(all,inv(mul(cnt-k,cnt-k))));
cout<<ans<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int T=1;
cin>>T;
while(T--)Main();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
2021-10-25 [CSP-S 2021] 廊桥分配 题解