CF1834题解

CF1834A

真水题

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=105;
int t,n;
int a[N];
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        int cnt=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]==-1)  cnt++;
        }
        int g=(n/4)*2;
        if(cnt<g)  printf("%d\n",cnt&1);
        else  printf("%d\n",cnt-g);
    }
}

CF1834B

比较神奇

考虑贪心

考虑如果高位限制比较宽松,那么一定会有形如x000000,y9999999这种情况是最优的

多一个9的贡献是我们最想要看到的

那x和y怎么订呢,直接找到高位上第一个不同的数字,然后加入原来

L:y....
R:x....

现在改为

x00000
y99999

是最优的

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n,m,ans;
string l,r;
int main(){
    scanf("%d",&t);
    while(t--){
        cin>>l>>r;
        n=l.length();
        m=r.length();
        ans=0;
        if(n==m){
            for(int i=0;i<n;i++){
                if(l[i]!=r[i]){
                    ans=abs((l[i]-'0')-(r[i]-'0'))+9*(n-i-1);
                    break;
                }
            }
        }
        else{
            if(n>m)  ans=abs((l[0]-'0'))+9*(n-1);
            else  ans=abs((r[0]-'0'))+9*(m-1);
        }
        printf("%d\n",ans);
    }
}


CF1834C

诈骗题

和先手后手没有关系,就讨论一下就可以

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int T,n;
char s[N],t[N];
int main(){
    scanf("%d",&T);
    while(T--){
        int cnt1=0,cnt2=0,ans1=0,ans2=0;
        scanf("%d",&n);
        scanf("%s",s+1);
        scanf("%s",t+1);
        for(int i=1;i<=n;i++){
            if(s[i]!=t[i])  cnt1++;
        }
        if(cnt1==0)  ans1=0;
        else if(cnt1&1)  ans1=2*cnt1-1;
        else  ans1=2*cnt1;
        for(int i=1;i<=n;i++){
            if(s[i]!=t[n-i+1])  cnt2++;
        }
        if(cnt2==0)  ans2=2;
        else if(cnt2&1)  ans2=2*cnt2;
        else  ans2=2*cnt2-1;
        printf("%d\n",min(ans1,ans2));
    }
}

CF1834D

想出来了,贪心

首先我们直接考虑最终手最低(设为b)和手最高(设为a)的两个人

考虑到选的手+1,不选手-1等价于选了后手+2

分两种情况考虑

  1. a包含b
  2. a不包含b

第一种情况是好做的

贪心的将长度最大的-长度最小的(因为如果选择的这两个不是包含关系答案会比这个大,在2情况会被统计到)

第二种情况

贡献为 a长度-a与b的交

所以枚举a,考虑让a与b的交最小

贪心的选择右端点最小,左端点最大的两种就可以了

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int t,n,m,lm,rm,ans,mlen,nlen;
int l[N],r[N];
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        lm=0;rm=m+1;mlen=0,nlen=m+1;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&l[i],&r[i]);
            mlen=max(r[i]-l[i]+1,mlen);
            nlen=min(nlen,r[i]-l[i]+1);
            lm=max(l[i],lm);
            rm=min(r[i],rm);
        }
        ans=mlen-nlen;
        for(int i=1;i<=n;i++){
            ans=max(ans,max(r[i]-max(rm+1,l[i])+1,min(r[i],lm-1)-l[i]+1));
        }
        printf("%d\n",ans*2);
    }
}

CF1834E

因为相当于是求一个 mex,所以我们考虑一下上界在什么位置

注意到 \(lcm(a,b)=a*b/gcd(a,b)\),有很好的性质

  1. 多一个数求 \(lcm\) 一定是只增不减的
  2. 如果能更新 \(lcm\) 那新的 \(lcm\) 最少是原来的二倍

所以 \(lcm\) 是以 log 倍增长的

所以对于一个 \(l\) 有效的 \(lcm\) 最多有 \(\log V\)

所以最多会有 \(n\log V\)\(lcm\),所以取的 mex 上界为 \(n\log V\)

问题变成了如何对于一个 \(l\) 求有效的 \(lcm\)

考虑维护一个 set存的是 \(1~l-1\) 中所有能组合出来的 \(lcm\)

然后再用 l 依次去更新,更新完后统计mex

由于上述证明,所以set中最多有 \(\log V\) 个元素

复杂度 \(n\log^2 V\)

posted @ 2025-08-29 11:26  daydreamer_zcxnb  阅读(11)  评论(0)    收藏  举报