Codeforces Round #748 (Div. 3) A D C D1 E(持续更新中)

Codeforces Round #748 (Div. 3)

A.Elections

思路:因为每个人是独立考虑,那么先从三个人中取一个MAX就好了,同时也要判断MAX的数量是不是大于1,如果大于1的话,说明如果当前数是最大他仍需要+1才能变成最大,同样如果MAX只有1个那么如果当前数是MAX那么他不需要操作。
参考code:
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int>S;
int a[5];
int main(){
    
    
    int t;
    cin>>t;
    while(t--){
    
    
        int MA=0;
        for(int i=1;i<=3;i++){
    
    cin>>a[i];MA=max(MA,a[i]);}
        S.clear();
        for(int i=1;i<=3;i++){
    
    
            if(a[i]==MA)S[MA]++;
        }
        for(int i=1;i<=3;i++){
    
    
            if(a[i]==MA&&S[MA]==1){
    
    
                cout<<0<<' ';
            }
            else if(a[i]==MA&&S[MA]>=1){
    
    
                cout<<1<<' ';
            }
            else{
    
    
                cout<<MA-a[i]+1<<' ';
            }
        }
        cout<<endl;
    }
    return 0;
}

B.Make it Divisible by 25

思路:首先思考什么数能被25整除,用字符串写,从字符串屁股着手,使用暴力枚举+双指针,时间复杂度最多(1e10*64^2)可以接受
参考code:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
void solve(){
    
    
    string s;
    cin>>s;
    int MI=2e9;
    for(int i=s.size()-1;i>=1;i--){
    
    
        int f=s.size()-1;
        if(s[i]=='0'){
    
    
            for(int j=i-1;j>=0;j--){
    
    
                if(s[j]=='5'||s[j]=='0'){
    
    
                    MI=min(MI,f-j-1);//f-j-1是因为s.size()-1~j之间的点除了i全部要删掉
                }
            }
        }
        else if(s[i]=='5'){
    
    
            for(int j=i-1;j>=0;j--){
    
    
                if(s[j]=='2'||s[j]=='7'){
    
    
                    MI=min(MI,f-j-1);
                }
            }
        }
    }
    cout<<MI<<endl;
}
int main(){
    
    
    IOS;
    int t;
    cin>>t;
    while(t--){
    
    
        solve();
    }
    return 0;
}

C. Save More Mice

一眼就可以发现这是一个裸贪心的问题,尽可能多的老鼠进洞,那么肯定是越近的先走,证明:(越近的老鼠先走,那么此老鼠的造成猫的偏移量一定小于远的老鼠先走造成猫的偏移量,那么同样是当第一个老鼠到达洞内,后者使得猫的偏移量更大,那么问题就转移成了后者猫的坐标更大,前者猫的坐标更小,那么必然后者导致老鼠逃脱的几率更小),需要注意猫最后的边界处理(我比赛时,没处理好导致wa了2发)
参考code:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
const int N=4e5+10;
int a[N];
ll b[N];
bool cmp(int a,int b){
    
    
    return a>b;
}
void solve(){
    
    
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=k;i++){
    
    
        cin>>a[i];
    }
    sort(a+1,a+1+k,cmp);
    for(int i=1;i<=k;i++){
    
    
        a[i]=n-a[i];
    }
    int cat=n-1;
    int res=0;
    for(int i=1;i<=k;i++){
    
    
        if(a[i]<=cat){
    
    
            cat-=a[i];
            res++;
        }
    }
    cout<<res<<endl;
}
int main(){
    
    
    IOS;
    int t;
    cin>>t;
    while(t--){
    
    
        solve();
    }
    return 0;
}

D1. All are Same

思路:首先很明显重复的数字我们可以去掉,因为不影响最终答案,比如2 3 3 和 2 3 是一样,然后因为本题要求的是如何使得这些数减去多个k(k尽量大)变成一样的数,如果k可以无穷大,那么输出-1,首先可以发现当所有数都是一样的话那么必定是-1,否则的话我们就要去算这些数差的共同gcd,(很像ccpc 2018桂林的G题),那么gcd就是最后最大的k
参考code:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
const int N=1e6+10;
int a[N];
int b[N];
int c[N];
unordered_map<int,int>S;
void solve(){
    
    
    int n;
    cin>>n;
    S.clear();
    for(int i=1;i<=n;i++){
    
    cin>>a[i];S[a[i]]++;}
    if(S[a[1]]==n){
    
    
        cout<<-1<<endl;
        return ;
    }
    sort(a+1,a+1+n);
    int cnt=0;
    for(int i=1;i<=n;i++){
    
    
        if(i==1||a[i]!=a[i-1])b[++cnt]=a[i];
    }
    if(cnt==2){
    
    
        int x=b[2]-b[1];
        cout<<x<<endl;
        return ;
    }
    else{
    
    
        int res=0;
        for(int i=2;i<=cnt;i++){
    
    
            c[++res]=b[i]-b[i-1];
        }
        int gd=c[1];
        for(int i=2;i<=res;i++){
    
    
            gd=gcd(gd,c[i]);
        }
        cout<<gd<<endl;
        return ;
    }
}
int main(){
    
    
    IOS;
    int t;
    cin>>t;
    while(t--){
    
    
        solve();
    }
    return 0;
}

E. Gardener and Tree

思路:本题听说可以使用多源bfs实现,等到时候学了之后可以试着再写一下,比较明显的是拓扑排序,度为1(因为是无向图)的点每次更新直到k结束时剩余的点,需要判断n==1时的情况,因为k>=1所以如果n == 1直接返回0即可
参考code:
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int e[N*2],ne[N*2],h[N],idx;
int ru[N];
int q[N];
int si[N];//si表示是第几次给淘汰的
void add(int a,int b){
    
    
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
int main(){
    
    
    int T;
    cin>>T;
    while(T--){
    
    
        int n,k;
        cin>>n>>k;
        if(n==1){
    
    
            cout<<0<<endl;
            continue;
        }
        memset(h+1,-1,n<<2);
        memset(ru+1,0,n<<2);
        memset(si+1,0,n<<2);
        idx=0;//每次初始化一下
        int gg=n-1;
        while(gg--){
    
    
            int a,b;
            cin>>a>>b;
            if(si[a]==0)si[a]=1;
            if(si[b]==0)si[b]=1;
            add(a,b);
            add(b,a);
            ru[a]++;
            ru[b]++;
        }
        int hh=0,tt=-1;
        for(int i=1;i<=n;i++){
    
    
            if(ru[i]==1)q[++tt]=i;//拓扑排序,入度为1进队。
        }
        while(hh<=tt){
    
    
            int x=q[hh++];
            for(int i=h[x];i!=-1;i=ne[i]){
    
    //每次用当前尾点去更新与其链接的点
                int j=e[i];
                if(--ru[j]==1){
    
    //如果度变成1,那么下一次他就是尾点,进队,且si层数在上一次基础上+1
                    si[j]=si[x]+1;
                    q[++tt]=j;
                }
            }
        } 
        int cnt=0;
        for(int i=1;i<=n;i++){
    
    
            if(si[i]>k)cnt++;//最后如果si>k说明没有在k次操作中删除,那么统计一下输出即可。
        }
        cout<<cnt<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_53504307/article/details/120767217
今日推荐