Codeforces Round #608 题解

A题

本题只需要对e,f进行大小比较,决定先买哪个即可,因为jacket对于每类都需要一个,所以以jacket为指标。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=10010;
int main(){
    int a,b,c,d,e,f;
    cin>>a>>b>>c>>d>>e>>f;
    int s1=min(b,c);
    if(e>f){
        int sum=0;
        if(a>d){
            sum=d*e;
        }
        else
        { sum=a*e+min(d-a,s1)*f;
        }
        cout<<sum<<endl;
    } 
    else{
        int sum=0;
        if(s1>d){
            sum=d*f;
        }
        else{
            sum=s1*f+min(a,d-s1)*e;
        }
        cout<<sum<<endl;
    }
} 
View Code

B题

根据对题目性质的研究,可以看出以下几点

1.变成全黑和全白都可以,所以做两遍判断。

2.考虑变白算法,可以先把两两相邻的黑色全部变白记录,这样剩下的黑色如果是奇数个,则变白不行,进行变黑,如果变黑也不行,那么输出-1

3.对于第一步后剩下的,直接从头开始翻转,必定可以做完。

4.注意特判初始全黑和全白情况。

学习点:一定要牢记特殊情况的判断。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=10010;
int pos[N];
int main(){
    int n;
    cin>>n;
    string s;
    cin>>s;
    s=" "+s;
    string b=s;
    int cnt=0;
    int i;
    int s1=0,s2=0;
    for(i=1;i<=s.size();i++){
        if(s[i]=='W')
        s1++;
    }
    if(s1==n||s1==0){
        
        cout<<0<<endl;
        return 0;
    }
    for(i=2;i<=s.size();i++){
        if(s[i]=='W'&&s[i-1]=='W'){
            pos[cnt++]=i-1;
            s[i]=s[i-1]='B';
        }
    }
    int sum=0;
    for(i=1;i<=s.size();i++){
        if(s[i]=='W')
        sum++;
    }
    if(sum%2){
        s=b;
        int cnt=0;
        int i;
        for(i=2;i<=s.size();i++){
        if(s[i]=='B'&&s[i-1]=='B'){
            pos[cnt++]=i-1;
            s[i]=s[i-1]='W';
        }
     }
    int sum=0;
    for(i=1;i<=s.size();i++){
        if(s[i]=='B')
        sum++;
    }
        if(sum%2){
            cout<<-1<<endl;
            
        }
        else{
            for(i=1;i<s.size();i++){
            if(s[i]=='B'){
                pos[cnt++]=i;
                s[i]='W';
                s[i+1]=s[i+1]=='W'?'B':'W';
            }
        }
        if(cnt>3*n){
            cout<<-1<<endl;
            return 0;
        }
        cout<<cnt<<endl;
        for(i=0;i<cnt-1;i++){
            cout<<pos[i]<<" ";
        }
        cout<<pos[i]<<endl; 
        }
        return 0;
    }
    else{
        for(i=1;i<s.size();i++){
            if(s[i]=='W'){
                pos[cnt++]=i;
                s[i]='B';
                s[i+1]=s[i+1]=='B'?'W':'B';
            }
        }
        if(cnt>3*n){
            cout<<-1<<endl;
            return 0;
        }
        cout<<cnt<<endl;
        for(i=0;i<cnt-1;i++){
            cout<<pos[i]<<" ";
        }
        cout<<pos[i]<<endl; 
    }
} 
View Code

C题

本题是一道思维题,我刚开始是考虑到,因为是最短路径,所以只要在(xi,sx)-(yi,sy)之间出现的点进行储存计算,后来发现数据范围很大,没有办法开这么大的数组,所以想到一定有简便方法

题目要求任意答案,我们知道所有最短路径都必须经过离学校长度为1的点,因此设计变量abcd如果x<sx,a++,x>sx,b++,y<sy,c++,y>sy,d++,这样比较四个的最大值,找到最大的把摊位设到学校旁边的位置

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=10010;
int pos[N];    
int l,r,u,d;
int main(){
    int n;
    cin>>n;
    int sx,sy;
    cin>>sx>>sy;
    int i;
 
    for(i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
        if(x<sx)
        l++;
        if(x>sx)
        r++;
        if(y>sy)
        u++;
        if(y<sy)
        d++;
    }
    int mx=0;
    mx=max(max(l,r),max(u,d));
    if(mx==l)
    sx-=1;
    else if(mx==r)
    sx+=1;
    else if(mx==u)
    sy+=1;
    else
    sy-=1;
    cout<<mx<<endl;
    cout<<sx<<" "<<sy<<endl;
} 
View Code

E题

本题于EOJ 1月月赛相同,我是根据别人算法看出规律。

/*
二分判y是否可行,judge函数里:
    找规律可以发现:
    y是奇数时
        第0层:y 
        第一层:2y,2y+1
        第二层:4y,4y+1,4y+2,4y+3
        第三层:8y,8y+1,8y+2,8y+3,8y+4,8y+5,8y+6,8y+7
            ...
        第k层:[2^k*y,2^k*y+2^k-1] 
    
    y是偶数时
        第0层:y,y+1 
        第一层:2y,2y+1,2y+2,2y+3 
        第二层:4y,4y+1,4y+2,4y+3,4y+4,4y+5,4y+6,4y+7
        第三层:8y,8y+1,8y+2,8y+3,8y+4,8y+5,8y+6,8y+7,8y+8,8y+9,8y+10,8y+11,8y+12,8y+13,8y+14,8y+15 
            ...
        第k层:[2^k*y,2^k*y+2^(k+1)-1] 
    
然后统计一下即可
特别注意,对起点是奇数偶数两种情况要特别注意一下,分开来进行二分 

*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll n,K;

ll Pow(ll a,ll b){
    ll res=1;
    while(b){
        if(b%2)res=res*a;
        b>>=1;a=a*a;
    }
    return res;
}
ll judge(ll y){
    ll sum=0,k=0;
    if(y%2==0){//偶数 
        while(Pow(2,k)*y+Pow(2,k+1)-1<=n){
            sum+=Pow(2,k+1);
            k++;
        }
        sum+=max(0ll,n-Pow(2,k)*y+1);
    }
    else {
        while(Pow(2,k)*y+Pow(2,k)-1<=n){
            sum+=Pow(2,k);
            k++;
        }
        sum+=max(0ll,n-Pow(2,k)*y+1); 
    }
    if(sum>=K)return 1;
    return 0;
}

int main(){
    cin>>n>>K;
    ll L=0,R=(n-1)/2,mid,ans1=1;
    while(L<=R){
        mid=L+R>>1;
        if(judge(mid*2+1))
            ans1=mid*2+1,L=mid+1;
        else R=mid-1;
    }
    
    L=1,R=n/2;
    ll ans2=1;
    while(L<=R){
        mid=L+R>>1;
        if(judge(mid*2))
            ans2=mid*2,L=mid+1;
        else R=mid-1;
    }
    cout<<max(ans1,ans2)<<'\n';
}
View Code

猜你喜欢

转载自www.cnblogs.com/ctyakwf/p/12210488.html