Codeforces Round #619 (Div. 2)

Codeforces Round #619 (Div. 2)

A. Three Strings

题意

给定abc三个字符串,c的每一位都必须与a或者b的对应位交换,问交换后的a和b是否可能相等

题解

由于c的每一位都必须交换,而交换后都要与另一个字符串的对应位比较,所以只需循环一遍,判断每一位c是否都能与a或者b对应位中的一个相等即可

代码

#include<iostream>
#include<cstdio>
using namespace std;
 
int main()
{   long N,i;
    string a,b,c;
    bool t;
    scanf("%ld",&N);
    while(N--){
        cin>>a>>b>>c;
        t=true;
        for(i=0;i<a.length();i++)
            if(c[i]!=a[i]&&c[i]!=b[i]){
                t=false;
                break;
            }
        if(t)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

B. Motarack’s Birthday

题意

给定一串数列,要求将其中的所有-1替换为同一个数k,求k使得替换后的整个数列相邻位之差的绝对值的最大值最小

题解

因为全部-1都替换为k,所以当-1两边的数与k的差值最小时,满足条件的k一定等于-1两边的(最大值+最小值)/2,替换后统计一遍即可

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define abs(i) (((i)>0)?(i):-(i))
#define def 100010
#define ll long long
using namespace std;
 
ll a[def];
 
int main()
{   ll N,n,i,num,ans,minn,maxx;
    scanf("%lld",&N);
    while(N--){
        memset(a,0,sizeof(a));
        scanf("%lld",&n);
        for(i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        minn=~(1<<31);
        maxx=0;
        for(i=1;i<=n;i++)
            if(a[i]==-1){
                if(i>1&&a[i-1]!=-1){
                    minn=min(minn,a[i-1]);
                    maxx=max(maxx,a[i-1]);
                }
                if(i<n&&a[i+1]!=-1){
                    minn=min(minn,a[i+1]);
                    maxx=max(maxx,a[i+1]);
                }
            }
        num=(maxx+minn)/2;
        for(i=1;i<=n;i++)
            if(a[i]==-1)
                a[i]=num;
        ans=0;
        for(i=1;i<n;i++)
            ans=max(ans,abs(a[i+1]-a[i]));
        if(minn!=~(1<<31))
            printf("%lld %lld\n",ans,num);
        else
            printf("%lld %lld\n",ans,0ll);
    }
    return 0;
}

C. Ayoub’s function

题意

定义 f ( s ) f(s) f(s)为字符串s包含1的字串的个数,给定n和m,构造一个n位的01字符串,其中1的个数为m个,使得 f ( s ) f(s) f(s)最大

题解

用组合数可以推出,一个字符串的子串个数为 C n + 1 2 = n ∗ ( n + 1 ) / 2 C^2_{n+1}=n*(n+1)/2 Cn+12=n(n+1)/2
由于只含0的字串比含1的字串统计更方便,所以考虑0的摆放位置。问题转化为:一共 ( n − m ) (n-m) (nm)个0,分成 m + 1 m+1 m+1份,使每一份字串个数最少,剩下的1就放在产生的 m m m个空位里。

易证一个结论: k ∗ ( k + 1 ) / 2 ∗ 2 < ( k − 1 ) ∗ k / 2 + ( k + 1 ) ∗ ( k + 2 ) / 2 k*(k+1)/2*2<(k-1)*k/2+(k+1)*(k+2)/2 k(k+1)/22<(k1)k/2+(k+1)(k+2)/2
所以均分产生的字串数量最少,如果无法完全均分,就尽量均分。

最终答案就是:总子串数-所有只含0的字串数

代码

#include<cstdio>
#define ll long long
 
int main()
{   ll N,n,m,p,r;
    scanf("%lld",&N);
    while(N--){
        scanf("%lld%lld",&n,&m);
        p=(n-m)/(m+1);
        r=(n-m)%(m+1);
        printf("%lld\n",n*(n+1)/2-r*(p+1)*(p+2)/2-(m+1-r)*p*(p+1)/2);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值