Codeforces Round #750 (Div. 2) A B C D F1

Codeforces Round #750 (Div. 2) A B C D F1

A. Luntik and Concerts

  • 思路:因为题目保证了a,b,c的数量至少为1,那么易得a,b,c可以任意组成0~a + b * 2 + c * 3 中的任意一个数字,那么为了使两个舞台的相差时间最短,那么显然判断a + b * 2 + c * 3 的奇偶性即可。
  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
int main(){
    
    
    snow;
    int t;
    cin>>t;
    while(t--){
    
    
        int a,b,c;
        cin>>a>>b>>c;
        ll ans=a+b*2+c*3;
        if(ans%2==0)cout<<0<<endl;
        else cout<<1<<endl;
    }
    return 0;
}

B. Luntik and Subsequences

  • 思路:B题其实模拟一下就很容易找到规律,因为要使他的子序列构成 nearly full,所以我们只要关注子序列中的0和1的数量即可。会容易发现最后的方案数是1的个数乘以2的出现数的次方即可,需要注意方案数最大是2^60次方需要开long long。
  • 参考代码
#include<bits/stdc++.h>
using namespace std;
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
const int N=65;
int a[N];
int main(){
    
    
    snow;
    int t;
    cin>>t;
    while(t--){
    
    
        int n;
        cin>>n;
        int res1=0,res0=0;
        for(int i=0;i<n;i++){
    
    
            cin>>a[i];
            if(a[i]==1)res1++;
            else if(a[i]==0)res0++;
        }
        ll ans=res1*pow(2,res0);
        cout<<ans<<endl;
    }
    return 0;
}

C. Grandma Capa Knits a Scarf

  • 思路:双指针扫描,最大时间复杂度是26*N,时间复杂度足够。
  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
const int N=65;
int a[N];
int main(){
    
    
    snow;
    int t;
    cin>>t;
    while(t--){
    
    
        int n;
        cin>>n;
        string s;
        cin>>s;
        int ans=n+1;
        for(char i='a';i<='z';i++){
    
    
            int l=0,r=s.size()-1;
            int cz=0;
            while(l<=r){
    
    
                if(s[l]==s[r]){
    
    
                    l++,r--;
                }
                else if(s[l]==i){
    
    
                    l++;
                    cz++;
                }
                else if(s[r]==i){
    
    
                    r--;
                    cz++;
                }
                else{
    
    
                    cz=n+1;
                    break;
                }
            }
            ans=min(ans,cz);
        }
        if(ans==n+1)cout<<-1<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}

D. Vupsen, Pupsen and 0

  • 思路:题目要求的是构造一个b数组,使得a[1]*b[1] + a[2]*b[2]… a[n]*b[n]=0,并且所有的 ∣ b [ 1 ] ∣ \left\vert b[1]\right\vert b[1]+… ∣ b [ n ] ∣ \left\vert b[n]\right\vert b[n]值要小于等于 1 0 9 10^9 109,显然偶数情况下我们只需要进行配对可以分成n/2个组合,例如a[1]和a[2]相对应的b[1]=a[2],b[2]=-a[1] 那么必定能使得最后的和的值为0。如果n是奇数的话,我们只需要将前面三个数进行处理例如 a[1] 和 a[2] 和 a[3] 相对应的 b[1]=a[3],b[2]=a[3] ,b[3]=-(a[1]+a[2]) 并且后面部分按照偶数情况处理那么便可以了,但是需要注意前面选择的三个数字可能会出现 a b c 但a = -b 的情况那么-(a+b)会变成0,显然与题目要求的b数组中不能出现0相悖,再仔细思考会发现我们只需要进行分类讨论前三个数即可,如果a=-b那么c的出现必然会使得三个数中至少其中两个数是正数或是负数,那么我们只需要让那两个正数或者负数为上面情况中的a和b那么-(a+b)必然不会是0,因此这个坑我们也可以巧妙处理了。
  • 参考代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int main(){
    
    
    snow;
    int t;
    cin>>t;
    while(t--){
    
    
        int n;
        cin>>n;
        if(n%2==0){
    
    
            int g=n/2;
            while(g--){
    
    
                int a,b;
                cin>>a>>b;
                cout<<-b<<' '<<a<<' ';
            }
            cout<<endl;
        }
        else if(n%2==1){
    
    
            int a,b,c;
            cin>>a>>b>>c;
            if(a==-b){
    
    
                if(b==c){
    
    
                    cout<<-(b+c)<<' '<<a<<' '<<a<<' ';
                }
                else if(a==c){
    
    
                    cout<<b<<' '<<-(a+c)<<' '<<b<<' ';
                }
                else{
    
    
                    cout<<-(b+c)<<' '<<a<<' '<<a<<' ';
                }
            }
            else{
    
    
                cout<<c<<' '<<c<<' '<<-(a+b)<<endl;
            }
            n-=3;
            int g=n/2;
            while(g--){
    
    
                cin>>a>>b;
                cout<<-b<<' '<<a<<' ';
            }
            cout<<endl;
        }
    }
    return 0;
}

F1.Korney Korneevich and XOR (easy version)

  • 思路:题目要求的是从A序列中选取一段上升序列(一开始读假题了),那么限制了可异或的条件,也就是132的话不能选取1 ^ 3 ^ 2的的值。本题n最大是1e5+10,a的值最大是500,熟悉了的话很快就能发现这是一个dp背包问题,并且由于5e7的复杂度尚可接受,本题可直接采取暴力dp背包求解。
  • 参考代码+详细注释:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int f[N];//用来表示当前异或值是否可得到,并且保留这个可异或得到的多个上升序列中最后一位最小。
#define snow ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//加速器
int main(){
    
    
    snow;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];//读入a序列
    memset(f,0x3f,sizeof f);//全部初始化为0x3f表示异或值尚不可得
    f[0]=0;//打开入口f[0]=0,因为0必定能得到且最小的最后一位必定是0。
    for(int i=1;i<=n;i++){
    
    
        for(int j=0;j<512;j++){
    
    //因为a的数值最大是500,在二进制中a所能异或得到的最大值为511
            if(f[j]<a[i])f[j^a[i]]=min(f[j^a[i]],a[i]);//为什么f[j]<a[i]才能进行转移呢?这个是本题的核心,因为我们题目
        }//要求的是选取一个上升序列,如果a[i]<f[j]则说明当前选取的a[i]比当前尽可能最小的状态表示值f[j]还小,那显然无法
    }//形成一个上升序列,与题目不符,当然f[j]<=a[i]也是可以的。min的存在也就是为了使得能到达f[j^a[i]]的最后一个值尽可能
    int res=0;//最小,很好理解,如果5^8=13和0^13=13。那么显然前者存的是8,后者存的是13,前者能够有更多机会去更新新的异或值
    for(int i=0;i<512;i++){
    
    //降低了异或的下限,多了更多的可能。
        if(f[i]<512)res++;//统计能够异或得到数量
    }
    cout<<res<<endl;
    for(int i=0;i<512;i++)if(f[i]<512)cout<<i<<' ';//将每个能够异或得到的输出,因为最大不超过511,所以扫一遍就好了。
    cout<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_53504307/article/details/120947079