Educational Codeforces Round 151 A~E
前言:F是个FFT,不想写。
A-Forbidden Integer
你需要构造一个正整数序列,满足:
- 对于
, 且 。 。
如无法构造,输出 NO
,否则输出 YES
后,输出序列长度与序列中的每一个数。
题解:
注意到顺序不重要,两个限制并不困难。考虑一种构造方案:整个序列有最少
我们枚举这个相同的数
int tag=0;
for(int i=1;i<=k;i++){
int y=n%i;
if(m==i)continue;
if(y+i<=k&&m!=y+i){
cout<<"Yes\n";
cout<<n/i<<"\n"<<y+i<<" ";
for(int j=2;j<=n/i;++j)cout<<i<<" ";
cout<<"\n";tag=1;break;
}
if(m==y)continue;
cout<<"Yes\n";
if(y==0){
cout<<n/i<<"\n";
for(int j=1;j<=n/i;++j)cout<<i<<" ";
}
else {
cout<<n/i+1<<"\n";
for(int j=1;j<=n/i;++j)cout<<i<<" ";cout<<y<<" ";
}
puts("");tag=1;break;
}
if(!tag)cout<<"No\n";
B-Come Together
给定无限大的网格图中
题解:考虑将横与纵分开看,我们实际要求的是线段
但是在代码实现中,我们直接通过做差的方式,这样会将拐点漏掉,加上就OK。
signed main(){
t=r();
while(t--){
int x1=r(),y1=r(),x2=r(),y2=r(),x3=r(),y3=r();
int a1=0,a2=0;
if(x1==x2&&x3==x1)a1=0;
else {
if(x1>min(x2,x3)&&x1<max(x2,x3))a1=0;
else a1=min(abs(x1-x2),abs(x1-x3));
}
if(y1==y2&&y3==y1)a2=0;
else{
if(y1>min(y2,y3)&&y1<max(y2,y3))a2=0;
else a2=min(abs(y1-y2),abs(y1-y3));
}
cout<<a1+a2+1<<"\n";
}
}
C-Strong Password
题面:给定一个字符串 m
的字符串
- 对于
, 。 不是 的一个子序列。
这题目NM是真的拗口,我的语文老师我对不起你啊
对于这种判断满足某种限制的存在性的问题,有经典套路:尝试构造符合条件的。
在本题中,最关键的地方是:各位相对独立,没有前后位之间的奇怪关系。题意也即要我们判断是否所有符合条件1的字符串都是它的子序列。我们可以先判断长度为
我们依次扫描原序列,设扫描到了
int j=0,sur=r[0]-l[0]+1;
for(int i=0;i<10;++i)val[i]=0;
for(int i=1;i<=n;i++){
if(l[j]<=s[i]&&s[i]<=r[j]&&val[s[i]-'0']==0)--sur,val[s[i]-'0']=1;
if(sur==0&&j==m-1){
cout<<"No\n";break;
}
if(!sur){
++j;sur=r[j]-l[j]+1;for(int i=0;i<10;++i)val[i]=0;
}
}
if(sur!=0||j!=m-1)cout<<"Yes\n";
D-Rating System
题面:给定一个长度为
- 如果
,则 ,否则 。
你需要求出
题解:容易发现,当
而,设
而我们本质上是将这几段区间和改为了0。但我们发现它虽然改了几段,但效果相同:等价于将
以
而这个的处理呢?我们倒着做一遍最小子段和的动态规划,就可以得到以某个点作为左端点的最小子段和了。设
而
注意这里不需要判断
int a[505050];
int get(int k){
int x=0;
for(int i=1;i<=n;i++){
if(x>=k)x=max(k,x+a[i]);
else x=x+a[i];
}
return x;
}
int f[505050];
signed main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>n;for(int i=1;i<=n;i++)cin>>a[i];
f[n+1]=0;
for(int i=n;i;--i){
f[i]=min(f[i+1]+a[i],a[i]);
}
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
}
int id=-1;
for(int i=1;i<=n;i++){
if(id==-1||f[id]>f[i])id=i;
}
cout<<a[id-1]<<"\n";
}
}
E-Boxes and Balls
关键:注意到一个数组可以通过两次操作不变化,这启发我们将恰好转化为奇偶性相同的最少
设
则
这是本题中第一个关键。
考虑对于一个新序列
第二个关键:由于元素只有1,0,则可以关注值相同的数的相对位置。
由于1不能与1交换,0不能与0交换,所以相对而言,1的顺序是固定的。设
由于前缀和数组与原数组形成双射(一一对应),故
合法的
(这里不难看出合法的
如何求出
考虑一个朴素的转移,有:
注意第一维在实现的时候要滚掉(此时
考虑优化。
这里注意到,将
那么,复杂度就降低到了
这里有另一个可以通过的做法,但时间复杂度稍劣(慢了大概二十倍)
那就是不维护
signed main(){
read(n),read(m);
for(int i=1;i<=n;i++){
read(s[i]);s[i]+=s[i-1];
}
f[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=min(s[n],s[i]+45ll);j>=max(0ll,s[i]-45ll);j--){
for(int k=m;k>=abs(s[i]-j);k--){
f[j][k]=f[j][k-abs(s[i]-j)];
if(j>0)f[j][k]=(f[j][k]+f[j-1][k-abs(s[i]-j)])%p;
}
for(int k=abs(s[i]-j)-1;k>=0;--k)f[j][k]=0;
}
}
int ans=0;
for(int i=m&1;i<=m;i+=2){
ans=(ans+f[s[n]][i])%p;
}
cout<<ans<<"\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!