牛客周赛52

A两数之和(枚举)


题意:输入一个正数z,找到两个不同的正整数x和y,使得x+y==z
分析:枚举x,y
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
    int z;cin>>z;
    for(int i=1;i<=z;i++){
        for(int j=1;j<=z;j++){
            if(i+j==z&&i!=j){
                cout<<"YES"<<endl;
                cout<<i<<" "<<j<<endl;
                return 0;
            }
        }
    }
    cout<<"NO"<<endl;
}


B小红装匣子(模拟)


题意:a块1×2大小的物块,b块1×3大小的物块,能否填满2×n的匣子?能输出YES否则NO
分析:先判断b能放几块,直接让b从左往右放,上面也要放,且一行不能超过n/3块,所以b能放min(b/2,n/3),如果a大于剩下的地方则YES
代码;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void sol(){
    ll a,b,n;cin>>a>>b>>n;
    b=b/2;b=min(b,n/3);
    if(n-b*3<=a)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}
int main(){
    int t;cin>>t;
    while(t--)sol();
    return 0;
}

C小红的数字对对碰


题意:有一个长度为n的数组a,可以进行以下操作减少数组长度。
i<j且ai+aj<=0,则可消去ai和aj;i<j且ai^aj<=0,则可消去ai和aj。输出最小化后的数组长度
分析:一正一负或两个相等的数,异或<=0,先把正数相同的数消掉,用cnt记录出现奇数次的数字的个数。如果cnt大于负数个数,让cnt-负数个数,剩下的正数无法继续处理,如果cnt小于负数个数,让负数-cnt,剩下的负数内部消除。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;cin>>n;int a[n+10];
    for(int i=1;i<=n;i++)cin>>a[i];
    map<int,int>mp;
    int fs=0;
    for(int i=1;i<=n;i++){
        if(a[i]>=0)mp[a[i]]++;
        else if(a[i]<0)fs++;
    }
    int cnt=0;
    for(auto &x:mp){
        if(x.second%2!=0)cnt++;
    }
    if(cnt>=fs)cout<<cnt-fs<<endl;
    else cout<<(fs-cnt)%2<<endl;
}


D小红的最大字典序


题意:小红有n个数字和一个空字符串,现在进行n次操作:第i次操作将ai按照数位上的相对顺序,从左到右取出并依次插入s,想构造一个这样的字符串,使得字典序是所有合法构造中最大
分析:用大根堆,每次推入字符串,输出堆头的第一个字符,然后将推头的第一个字符移除
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;cin>>n;
    priority_queue<string>q;
    for(int i=0;i<n;i++){
        string s;cin>>s;
        q.push(s);
    }
    while(!q.empty()){
        string ss=q.top();
        q.pop();
        cout<<ss.front();
        if(ss.size()!=1)q.push(ss.substr(1));
    }
}

E小红的图上加边(并查集)


题意:有一个n点m边的无向图,每个节点的权值是ai,每次连接的代价是新形成的连通块的最大元素的值,最小需要消耗多少代价可以把这个图连成连通的
分析:用并查集,每次遍历将祖先的权值更新为俩节点的祖先的权值的最大值。然后用ans将所有祖先的权值相加,减去最小祖先权值。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
ll f[N];
ll zx(ll x){
    if(f[x]==x)return x;//x没爸爸
    else return f[x]=zx(f[x]);//找出爸爸的爸爸的。。 
}
void h(ll x,ll y){
    f[zx(y)]=zx(x);//x的最大祖先变成y最大祖先的爸爸; 
}
int main(){
    ll n,m;cin>>n>>m;ll ans=0,mi=0x3f3f3f3f;
    ll u,v;
    for(int i=1;i<=n;i++){
        cin>>a[i];f[i]=i;
    }
    for(int i=1;i<=m;i++){
        cin>>u>>v;
        a[zx(v)]=max(a[zx(v)],a[zx(u)]);
        a[zx(u)]=max(a[zx(v)],a[zx(u)]);
        h(u,v);
    }
    for(int i=1;i<=n;i++){
        if(zx(i)!=i)continue;
         ans+=a[i];
        mi=min(mi,a[i]);
    }
    cout<<ans-mi<<endl;
    return 0;
}


F小红的括号串


题意:有多少种将?替换成左括号或右括号的方案,字符串可以循环移位,使得该字符串为合法的括号串。合法的括号串:左括号数量=右括号数量,俩俩相匹配。
分析:可以将左括号看出+1,右括号-1,只要前缀和总是>=0,它就是合法的括号串,由于可以循环移位,所以一定可以循环移位到一中前缀和全部>=0的。如果字符串长度为奇数,他的左括号和右括号永远不相等。所以我们把问号改成字符串左括号等于右括号即可,用二项式求出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9+7;
ll f[N],invf[N];
ll ksm(ll a,ll b){
    ll res=1%mod;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll inv(ll x){
    return ksm(x,mod-2);
}
ll C(ll a,ll b){
    return f[a]*invf[b]%mod*invf[a-b]%mod;
}
void init(){
    f[0]=invf[0]=1;
    for(int i=1;i<N;i++){
        f[i]=f[i-1]*i%mod;
        invf[i]=inv(f[i])%mod;
    }
}

int main(){
    ll n;cin>>n;ll kuohao=0;
    string s;cin>>s;init();
    if(n%2!=0){
        cout<<"0"<<endl;
        return 0;
    }
    ll cnt=0;
    for(int i=0;i<s.size();i++){
        if(s[i]=='(')kuohao++;
        else if(s[i]==')')kuohao--;
        else cnt++;
    }
    cout<<C(cnt,(kuohao+cnt)/2)<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值