【Virt.Contest】CF1215(div.2)
第二次打虚拟赛。
CF 传送门
T1:Yellow Cards
黄色卡片
中规中矩的
首先可以算出一个人也不罚下时发出的最多黄牌数:
此时,若
然后看最多。优先考虑全部发给所需黄牌数少就能下场的一队。如果全下光了,就去发给另一队。
不得不说这比赛机制简直找打
Code:
#include<bits/stdc++.h>
using namespace std;
int a1,a2,k1,k2,n,sum,tmp;
int main(){
scanf("%d%d%d%d%d",&a1,&a2,&k1,&k2,&n);
sum=a1*(k1-1)+a2*(k2-1);
printf("%d ",max(0,n-sum));
if(k1>k2){
swap(k1,k2);
swap(a1,a2);
}
tmp=n/k1;
if(tmp>a1){
n-=a1*k1;
printf("%d",a1+n/k2);
}
else printf("%d",tmp);
return 0;
}
T2:The Number of Products
一开始想的是用前缀和算每个区间的负数个数,但是
后来想到可以对每一次读入快速判。设置一个标记记录当前正负状态。如果标记为正,那么正答案加上之前所有的正区间、负答案加上之前所有负区间(不变号)。如果标记为负,那么正答案加上之前所有的负区间、负答案加上之前所有正区间(变号)。
然鹅样例都过不了,一度怀疑做法假了。就去看了眼
Code:
#include<bits/stdc++.h>
using namespace std;
long long n,a,z,f,ans1,ans2,fl=1;
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a);
if(a<0) fl=-fl;
if(fl>0) ans1+=z,ans2+=f,z++;
else ans1+=f,ans2+=z,f++;
}
printf("%lld %lld",ans2+f,ans1+z);
return 0;
}
T3:Swap Letters
一开始读错题,以为是单个字符串内部交换。心想怎么会这么水。对着样例才发现了错误。
首先容易得知,两个字符串中
其次考虑怎么交换。对照样例三:
in:
8
babbaabb
abababaa
out:
3
2 6
1 3
7 8
发现,每一对交换的字符有共同点:
-
要不是串一都为
,串二都为 的一对 -
要不是串一都为
,串二都为 的一对
简单思考后发现这样成对交换就是最优的。(换一次就可以匹配上两位)
于是,考虑先统计出 串一为
这时发现一个问题,
这时就出现了样例一的情况:
in:
4
abab
aabb
out:
2
3 3
3 2
只要按着样例一的方式特判输出即可。
Code:
#include<bits/stdc++.h>
using namespace std;
int n,ans1[200005],ans2[200005],cnt,cnt1,cnt2;
string s1,s2;
int main(){
scanf("%d",&n);
cin>>s1>>s2;
for(int i=0;i<n;i++){
if(s1[i]=='b') cnt++;
if(s2[i]=='b') cnt++;
}
if(cnt%2==1) printf("-1");
else{
for(int i=0;i<n;i++){
if(s1[i]=='a'&&s2[i]=='b') ans1[++cnt1]=i+1;
if(s2[i]=='a'&&s1[i]=='b') ans2[++cnt2]=i+1;
}
if(cnt1%2==0){
printf("%d\n",cnt1/2+cnt2/2);
for(int i=1;i<=cnt1;i+=2){
printf("%d %d\n",ans1[i],ans1[i+1]);
}
for(int i=1;i<=cnt2;i+=2){
printf("%d %d\n",ans2[i],ans2[i+1]);
}
}
else{
printf("%d\n",cnt1/2+cnt2/2+2);
for(int i=1;i<=cnt1-1;i+=2){
printf("%d %d\n",ans1[i],ans1[i+1]);
}
for(int i=1;i<=cnt2-1;i+=2){
printf("%d %d\n",ans2[i],ans2[i+1]);
}
printf("%d %d\n",ans1[cnt1],ans1[cnt1]);
printf("%d %d\n",ans1[cnt1],ans2[cnt2]);
}
}
return 0;
}
T4:Ticket Game
看上去是高大上的博弈论问题,实际就是贪心。
考虑把字符串分成左右两部分,分别统计出两边的 ?
个数 ?
的数字之和
因为 Monocarp
先手,而 Bicarp
要维护字符串两边和相等,所以在两边都还有 ?
时,Monocarp
填任意一个, Bicarp
必然在另一边填一个相等的数字。所以,这些过程对结果是无意义的,可以把两边都有的 ?
个数抹掉。
于是,问题就变成了一边都是数,在另一边填数。由题意,问号为偶数个,所以原来两边问号奇偶相同,减掉后剩下的问号也为偶数个。
这时我们发现,问题很像小学奥数里的取棋子游戏。就是每人每次取一个或两个,取到最后一个者胜,判断先后手谁胜。易知,棋子总数为
假设剩下的 ?
都在右边,问题就变成两人轮流填
得出结论:只要 Bicarp
胜。反之则 Monocarp
胜。
因为赛时很快想到思路,代码实现也简单,所以成为拉分的一题。
Code:
#include<bits/stdc++.h>
using namespace std;
int n,ls,rs,l,r;
string s;
int main(){
scanf("%d",&n);
cin>>s;
for(int i=0;i<n/2;i++){
if(s[i]=='?') l++;
else ls+=s[i]-'0';
}
for(int i=n/2;i<n;i++){
if(s[i]=='?') r++;
else rs+=s[i]-'0';
}
if(l>r){
swap(l,r);
swap(ls,rs);
}
r-=l;
if(r/2*9+rs==ls) printf("Bicarp");
else printf("Monocarp");
return 0;
}
T5:Marbles
状压
一个结论:把一个序列变为不降所需要的相邻元素交换次数就是这个序列的逆序对数。
那么这题要我们干的是什么呢?就是按颜色变为不降,只不过颜色的大小顺序我们可以任意指定而已。比如样例
看到颜色数最多
假设已经安排好
——来自
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a[400005],cnt[25];
ll b[25][25],f[2000005];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=1;j<=20;j++) b[j][a[i]]+=cnt[j];
cnt[a[i]]++;
}
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int k=0;k<(1<<20);k++){
for(int i=1;i<=20;i++){
if((k>>(i-1))&1) continue ;
ll tmp=0;
for(int j=1;j<=20;j++){
if((k>>(j-1))&1) tmp+=b[j][i];
}
f[k|(1<<(i-1))]=min(f[k|(1<<(i-1))],f[k]+tmp);
}
}
printf("%lld\n",f[(1<<20)-1]);
return 0;
}
T6:Radio Stations
施工中
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话