Codeforces Round #624 (Div. 3)

之前开的一场虚拟赛,鸽了好久,今天找了个时间把题解写了
给个传送门

A. Add Odd or Subtract Even
题意:给你两个数a,b 你可以在给a加上一个奇数或者减去一个偶数使a变成b,问你最少需要操作几次。

很简单,a==b不需要操作,a>b 如何a-b 是奇数,那么加上个奇数就行,如果是偶数,那么加上一个大一点的奇数再减1就行,同理a<b。


#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
 
int main (){
     int n;
     cin>>n;
     while(n--){
        int a,b;
        cin>>a>>b;
        if(a==b){
            cout<<0<<endl;
        }
        else if(a<b){
            if((b-a)%2==1)cout<<1<<endl;
            else cout<<2<<endl;
        }
        else if(a>b){
            if((a-b)%2==1)cout<<2<<endl;
            else cout<<1<<endl;
        }
     }
 
 
    return 0;
}

B.WeirdSort
题意: 给你一个数组,然后告诉你哪些地方可以进行操作,操作是和它后面的那个数进行交换,最后问你能否交换出一个不下降的序列。

最开始的想法是,任意一个比相邻的数的后面那个大的话就必须要能操作,发现wa了,才明白是想法不对。好在及时改正,我的思路是,某个数要想变成不下降的顺序,那么如果他前面有一个数比他大,那么这两个数之间必须都要能进行交换操作。具体看代码。

#include <bits/stdc++.h>
using namespace std;
const int N=105;
int a[N],p[N];
int main (){

    int t;
    cin>>t;
    while(t--){
        int n,m,x;
        cin>>n>>m;
        memset(p,0,sizeof(p));
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=0;i<m;i++)cin>>x,p[x]=1;
        int flag=0;
        for(int i=1;i<=n;i++){
                int ans=100;
            for(int j=1;j<i;j++){
                if(a[j]>a[i]){
                    ans=j;
                    break;
                }
            }

            for(int j=ans;j<i;j++){
                if(p[j]!=1){
                    cout<<"NO"<<endl;
                    flag=1;
                    break;
                }
            }
            if(flag==1)break;
        }
        if(flag==0)
        cout<<"YES"<<endl;
    }
    return 0;
}

c.Perform the Combo
题意: 举个例子说吧。你在玩一个字符串敲击游戏。比如你现在要敲abca ,但是告诉你你会在敲第3下的地方失败,那么你就要重新敲,这样你就敲了abc,abca一共7下,告诉你一系列会失败的地方,问你最后26个字母分别敲了几下。

这题其实挺有意思的,数据 2 ∗ 1 0 5 2*10^5 2105 暴力的话 O ( n 2 ) O(n^2) O(n2) 的复杂度肯定会爆。网上以及官方题解都是使用前缀和做的。比赛的时候这题做了挺久,好在后面A了,我的算法不太一样。简单讲讲怎做吧。
比放说我们要求codeforces这么一个字符串。
出错的地方分别是2 8 3 2 9
那么我们就要统计这么一些子串
co codeforc cod co codeforce
怎么做呢,先将他们按长度排序
co
co
cod
codeforc
codeforce
为什么要竖着写呢?这样从左往右统计字符串的时候就有规律可言,比如说第一个字符c,它在每个字符串里都出现过,所以我们直接先加5,o也是,d的时候前两个字符串就没了,所以加 5 − 2 5-2 52 ,为什么是 5 − 2 5-2 52呢,第三个字符串出现的起始位置是第3个到最后,前面两个没有了。具体可以看代码。

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
char ch[N];
int p[N];
int a[30];
int main (){
    int t;
    cin>>t;
    while(t--){
        memset(a,0,sizeof(a));
        int n,m;
        scanf("%d%d",&n,&m);
        cin>>ch;
        for(int i=0;i<m;i++){
                cin>>p[i];
        }
        sort(p,p+m);
        int x=0;

        for(int i=0;i<n;i++){
            while(i>(p[x]-1)){
                if(x==m) break;
                x++;

            }
            a[ch[i]-'a']+=(m-x+1);

        }
        for(int i=0;i<26;i++){
            printf("%d ",a[i]);
        }
        puts("");
    }

    return 0;
}

D - Three Integers
题意: 给你 a < = b < = c a<=b<=c a<=b<=c三个数,你可以对他们呢进行加1减1的操作,问你最少一共操作多少次使得 c c c可以整除 b b b b b b 可以整除 a a a .

思路其实就是暴力,但是有一定的技巧。比如说枚举a的时候只需要从 1 − 2 ∗ a 1-2*a 12a 即可,因为问的是最少次数,如果你超过 2 ∗ a 2*a 2a,你不如直接变成1。 枚举b的时候道理是一样的,可以可以只枚举a的倍数,每次都加a。因为要求的是最少次数,所以最后求c的时候,
c = ⌊ c / b ⌋ ∗ b c=\lfloor c/b \rfloor *b c=c/bb 或者是
c = ⌈ c / b ⌉ ∗ b c=\lceil c/b \rceil *b c=c/bb
这样可以保证次数一定是最小的。

#include <bits/stdc++.h>
using namespace std;
int A,B,C,ans,cnt;
int main(){
    int n;
    cin>>n;
    while(n--){
        int a,b,c;
        cin>>a>>b>>c;
        ans=1e9,cnt=0;
        for(int i=1;i<=2*a;i++){
            for(int j=i;j<=2*b;j+=i){
                int c1=(c/j)*j;
                int c2=(c/j+1)*j;
                if(c1>=j){
                    cnt=abs(i-a)+abs(j-b)+abs(c-c1);
                    if(ans>cnt){
                        ans=cnt;
                        A=i;
                        B=j;
                        C=c1;
                    }
                }
                if(c2>=j){
                    cnt=abs(i-a)+abs(j-b)+abs(c-c2);
                    if(ans>cnt){
                        ans=cnt;
                        A=i;
                        B=j;
                        C=c2;
                    }
                }
            }
        }
        cout<<ans<<endl<<A<<" "<<B<<" "<<C<<" "<<endl;
    }


    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值