Educational Codeforces Round 82 (Rated for Div. 2) 部分题解

传送门

A题: 将夹杂在1中的0给删除即可。

#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=2e5+5;
 
 
int main()
{
    string s;
    int T;
    scanf("%d",&T);
    while(T--){
        cin>>s;
        int j=0,k=0,num=0;
        int n=s.size();
        for(int i=0;i<n;i++){
            if(s[i]=='1'){j=i;break;}
        }
        for(int i=n-1;i>=0;i--){
            if(s[i]=='1'){k=i;break;}
        }
        for(int i=j;i<k;i++){
            if(s[i]=='0'){num++;}
        }
        printf("%d\n",num);
    }
    return 0;
}

B题: 答案具有单调性,直接二分枚举最少天数

#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=2e5+5;
 
bool check(ll mid,ll g,ll b,ll n)
{
    n=(n+1)/2;
    ll m=g+b;
    if((mid/m*g+min(mid%m,g))>=n){return true;}
    else{return false;}
}
int main()
{
    int T;
    ll n,g,b;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld",&n,&g,&b);
        ll l=n,r=1e18,ans;
        while(l<=r){
            ll mid=(l+r)>>1;
            if(check(mid,g,b,n)){
                ans=mid,r=mid-1;
            }
            else{
                l=mid+1;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

C题: dfs+建边。
1.相邻字符建立一条边,再判断一个字符是否最多相邻两个字符。
2.对 度数 < 2 && 未访问字符 进行dfs。(为啥对度 < 2 的进行搜索呢? 你想一下,情况1:孤立的一个字符;情况2:仅连接一个字符。我们假设答案YES的话,那么最终的排序必然是一条链,我们对孤立字符不考虑的话,那可以对链两端( 度1 )开始dfs出该链,若你对度2的考虑你的链将不正确,无法准确排出另一方向的链)
3.若存在为访问的点(度都为2构成环去了),直接输出NO

#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;

string p;
char s[205];
bool vis[30],ans[30][30];
int indx[30];

void dfs(int now)
{
    if(vis[now]){return ;}
    vis[now]=true;p+=now+'a';
    for(int i=0;i<26;i++){
        if(!vis[i]&&ans[now][i]){
            dfs(i);
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        mem(ans,false);mem(vis,false);mem(indx,0);p="";
        scanf("%s",s+1);
        for(int i=2;s[i];i++){
            int a=s[i-1]-'a';
            int b=s[i]-'a';
            ans[a][b]=ans[b][a]=true;
        }
        for(int i=0;i<26;i++){
            ans[i][i]=false;
            for(int j=0;j<26;j++){
                if(ans[i][j]){indx[i]++;}
            }
        }
        bool flag=false;
        for(int i=0;i<26;i++){
            if(indx[i]>2){printf("NO\n");flag=true;break;}
        }
        if(flag){continue;}
        for(int i=0;i<26;i++){
            if(!vis[i]&&indx[i]<2){dfs(i);}
        }
        for(int i=0;i<26;i++){
            if(!vis[i]){printf("NO\n");flag=true;break;}
        }
        if(flag){continue;}
        printf("YES\n");cout<<p<<endl;
    }
    return 0;
}

D题: 直接暴力处理即可。
1.可以直接判断无法构成的情况。
2.预先处理出二进制状态下每位的个数 bit[] ,再将n转化为二进制形式从低位开始处理,如果该位bit[]>0,说明可以用去组合;反之,向高位寻找第一个bit[]>0,然后用它去拆分直至拆分到当前位。
3.处理完当前位后,需进行合并到高位,bit [i+1] += bit [i] / 2;

#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
 
int bit[66];
 
int main()
{
    int T,m,ant,cnt;
    ll sum,n;
    scanf("%d",&T);
    while(T--){
        mem(bit,0);cnt=0;sum=0;
        scanf("%lld%d",&n,&m);
        for(int i=1,j;i<=m;i++){
            scanf("%d",&j);sum+=j;
            for(int k=0;k<30;k++){
                if((1<<k)==j){bit[k]++;}
            }
        }
        if(sum<n){printf("-1\n");continue;}
        for(int i=0;i<60;i++){
            if(n&(1ll<<i)){
                for(int j=i;j<60;j++){
                    if(bit[j]){
                        bit[j]--;
                        for(int k=i;k<j;k++){
                            bit[k]++;
                        }
                        break;
                    }
                    cnt++;
                }
            }
            bit[i+1]+=bit[i]/2;
        }
        printf("%d\n",cnt);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值