buct蓝桥杯选拔赛题解

A.签到题

#include <bits/stdc++.h> 
using namespace std;
typedef long long ll;
int main(){
    int a,b,c;
    cin>>a>>b>>c;
    a=a-b;
    a=min(a,c);
    // cout<<a<<endl;
    c=c-a;
    cout<<c<<endl;
    return 0;
}

B.签到题

#include <bits/stdc++.h> 
using namespace std;
typedef long long ll;
int check( int x){
    int cnt=0;
    while(x){
        cnt++;
        x/=10;
    }
    if(cnt%2==1) return 1;
    return 0;
}
int main(){
    int n;
    cin>>n;
    int ans=0;
    for( int i=1;i<=n;i++){
        if(check(i)) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

C.贪心算法

只要该位置能减一,就减一

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int w[100100];
int main(){
    int n;
    cin>>n;
    for( int i=1;i<=n;i++){
        scanf("%d",&w[i]);
    }
    for( int i=1;i<=n;i++){
        if(w[i]>w[i-1]) w[i]--;
        else if(w[i]==w[i-1]){
            continue;
        }
        else {
            cout<<"No"<<endl;
            return 0;
        }
    }
    cout<<"Yes"<<endl;
}

D.模拟题

找到L左侧的第一个R
找到R右侧的第一个L

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int w[100100];
int R[100100];//从左向右跳,距离最近的L的距离
int L[100100];//从有向左跳,距离最近的R的距离
int ans[100100];
int main(){
    string s;
    cin>>s;
    for( int i=0;i<s.size();i++){
        if(s[i]=='L'&&i-1>=0&&s[i-1]=='R'){
            L[i]=1;    
        }
        if(s[i]=='R'&&i+1<s.size()&&s[i+1]=='L'){
            R[i]=1;
        }
    }
    for( int i=0;i<s.size();i++){//从有向左
        if(s[i]=='R') continue;
        else{
            if(L[i]==0) L[i]=L[i-1]+1;
        }
    }
    for( int i=s.size()-1;i>=0;i--){//从左向右
        if(s[i]=='L' ) continue;
        else {
            if(R[i]==0) R[i]=R[i+1]+1;
        }
    }
    for( int i=0;i<s.size();i++){
        if(s[i]=='L'){
            int x=i-L[i]+L[i]%2;
            ans[x]++;
        }
        else {
            int x=i+R[i]-R[i]%2;
            ans[x]++;
        }
         
    }
    for( int i=0;i<s.size();i++){
        printf("%d ",ans[i]);
    }
    return 0;
}

E。

找到所有因数,然后判断每个因数是否符合答案
判断方法是贪心,每次取最小值加到最大值上

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll w[510];
int n,k;
ll check( ll x){
    int cnt=0;
    set<pair<ll,ll> >se;
    for( int i=1;i<=n;i++){
        se.insert(make_pair(w[i]%x,cnt++));
    }
    ll now=0;
    ll res=0;
    for( int i=1;i<=n;i++){
        if(now<=0) {
            set<pair<ll,ll> >::iterator  it=se.begin();
            ll y=it->first;
            se.erase(it);
            now+=y;
            if(now>0) res+=now;
        }
        else{
            set<pair<ll,ll> >::iterator it=se.end();
            it--;
            ll y=it->first;
            se.erase(it);
            now-=(x-y);
            if(now<0) res+=-now;
        }
    }
    return res;

}
int main(){
    cin>>n>>k;
    ll sum=0;
    vector<ll>v;
    for( int i=1;i<=n;i++){
        cin>>w[i];
        sum+=w[i];
    }
    for( int i=1;i*i<=sum;i++){
        if(sum%i!=0) continue;
        v.push_back(sum/i);
        v.push_back(i);
    }
    ll ans=0;
    for( int i=0;i<v.size();i++){
        if(check(v[i])<=k){
            ans=max(ans,v[i]);
        }
    }
    cout<<ans<<endl;
    return 0;
}

F

在这里插入图片描述
本题实际上就是求解每个点出现的次数
我们将某个点出现分为两种情况:
第一种情况:该点直接在集合中出现
第二种情况:该点被矩形包围,但是没有在集合中出现

对于第一种情况,使用计数原理直接求解
第二种情况,使用容斥原理加平衡树求解
注意取模

#include<bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
const int N=200100;
const ll mod=998244353;
struct Point{
    ll x,y;
}p[N];
int cmp(Point a,Point b){
    return a.x<b.x;
}

ll onTheLeft_up[N],onTheLeft_down[N],onTheRight_up[N],onTheRight_down[N];
ll powerof2[N];
void cal( ){
    powerof2[0]=1;
    for( int i=1;i<=200010;i++){
        powerof2[i]=powerof2[i-1]*2;
        powerof2[i]%=mod;
    }
    return ;
}
int main(){
    int n;
    cin>>n;
    cal();
    for( int i=1;i<=n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
    }
    sort(p+1,p+1+n,cmp);
    tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update >t1;
    for( int i=1;i<=n;i++){
        onTheLeft_down[i]=t1.order_of_key(p[i].y);
        onTheLeft_up[i]=t1.size()-onTheLeft_down[i];
        t1.insert(p[i].y);
    }
    tree<ll,null_type,greater<ll>,rb_tree_tag,tree_order_statistics_node_update >t2;
    for( int i=n;i>=1;i--){
        onTheRight_up[i]=t2.order_of_key(p[i].y);
        onTheRight_down[i]=t2.size()-onTheRight_up[i];
        t2.insert(p[i].y);
    }
    ll ans=1ll*n*powerof2[n-1]%mod;//直接包含的情况
    //下面计算被覆盖的情况
    for( int i=1;i<=n;i++){
        ll x=onTheRight_down[i],y=onTheLeft_up[i];
        ll a=onTheRight_up[i],b=onTheLeft_down[i];
        ans+=(powerof2[x]-1)*(powerof2[y]-1)%mod*(powerof2[a]+powerof2[b]-1);
        ans%=mod;
        ans+=(powerof2[a]-1)*(powerof2[b]-1)%mod*(powerof2[x]+powerof2[y]-1);
        ans%=mod;
        ans+=((powerof2[a]-1)*(powerof2[b]-1)%mod)*((powerof2[x]-1)*(powerof2[y]-1)%mod);
        ans%=mod;
        
    }
    cout<<ans<<endl;
    
    return 0; 
}

G.直接算的。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    long long n;
    cin>>n;
    long long  be=1;
    long long cnt=n;
    long long pow=1;
    int flag=0;
    while(cnt!=1){
        if(cnt%2==0){
            if(flag==1){
                be+=pow;
            }
            cnt/=2;
            pow*=2;
        }
        else if(cnt%2==1){
            if(flag==1)
            be+=pow;
            pow*=2;
            cnt/=2;
            if(flag==1){
                flag=0;
            }
            else {
                cnt++;
                flag=1;
            }
             
        }
    }

    cout<<be<<endl;
    
    return 0;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值