• Codeforces Round #539 (Div. 2) 题解


    Codeforces Round #539 (Div. 2)

    题目链接:https://codeforces.com/contest/1113

    A. Sasha and His Trip

    题意:

    n个城市,城市分布在一条直线上且按升序排序,现在有个人开车从一号城市出发,车的油箱容量为v。

    在每个城市都可以买油,但价格不一样:第i个城市买1单位的油花费i元。问最终从1到n花费的最少为多少。

    题解:

    贪心即可,尽量在前面的城市买油,最后一鼓作气到n号城市。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+5;
    int n,v;
    int main(){
        cin>>n>>v;
        int fir=2,las=n-v;
        int ans=v;
        if(n-1<=v){
            cout<<n-1;
            return 0;
        }
        for(int i=2;i<=las;i++){
            ans+=i;
        }
        cout<<ans;
        return 0;
    }
    View Code

    B. Sasha and Magnetic Machines

    题意:

    给出n个数,现在选定i,j,然后取x满足aj%x==0,之后让aj=aj/x,ai=ai*x。这个操作最多一次,问最后所有数的和最小为多少。

    题解:

    由于这里ai<=100,并且n也最多1e4,所以可以直接考虑暴力。但这里暴力的是,取到一个x的时候,应该始终就是让最小的那个ai来乘x,这应该是显而易见的。

    具体见代码吧:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5;
    int a[N];
    int n;
    int main(){
        scanf("%d",&n);
        int sum = 0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        int ans = sum;
        int mn = *min_element(a+1,a+n+1);
        sum-=mn;
        for(int i=1;i<=n;i++){
            for(int j=2;j<=a[i];j++){
                if(a[i]%j!=0) continue ;
                ans=min(ans,sum-a[i]+a[i]/j+mn*j);
            }
        }
        cout<<ans;
        return 0;
    }
    View Code

    C. Sasha and a Bit of Relax

    题意:

    给出n个数,然后让你找出满足条件的区间个数:区间长度为偶数且区间左部分的异或和等于右部分的异或和。

    题解:

    根据题中条件可以知道,那整个区间的异或和是为0的,然后根据异或前缀和进一步可知:假设那个区间为[l,r],那么prel-1=prer,这里prei为1~i的异或前缀和。并且还可以观察到,这里的l-1以及r是同奇偶的。

    然后做法也大致清晰了,找出在奇偶位置异或前缀和为x的个数,假设我们目前只看奇数位置,有n个,那么这时对答案的贡献为C(n,2),也即是n*(n-1)/2;偶数也同样。

    只是需要注意的是,当前缀异或和为0并且当前为偶数位置时,这也算一种情况。

    具体代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int cnt[2][1<<20];
    int main(){
        int n;
        cin>>n;
        vector <ll> a(n+2);
        for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
        ll sum=0,ans=0;
        cnt[0][0]=1;
        for(int i=1;i<=n;i++){
            sum^=a[i];
            ans+=cnt[i%2][sum];
            cnt[i%2][sum]++;
        }
        cout<<ans;
        return 0;
    }
    View Code

    D. Sasha and One More Name

    题意:

    给出一个回文串,然后让你用最少的次数分割为几个部分,之后可以拼接出一个和原来不同的回文串。如果不能就输出"Impossible",否则输出最少次数。

    题解:

    不能的情况很好判断。

    在判断可行性过后,可以证明次数最多只需要两次,考虑从两边同时往中间走的切法就行了。

    也就是说,我们只需要判断只切一次是否可行。由于字符串的长度只有5000,O(n^2)暴力即可。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 5005;
    string s;
    int l;
    bool is(string ss){
        int f=1;
        for(int i=0;i<l;i++){
            int j=l-i-1;
            if(ss[i]!=ss[j]) f=0;
        }
        return f&&ss!=s;
    }
    int main(){
        cin>>s;
        l=s.length();
        int f=1;
        for(int i=1;i<l;i++){
            if(l&1 && i==l/2) continue ;
            if(s[i]!=s[0]) f=0;
        }
        if(f){
            puts("Impossible");
            return 0;
        }
        f=0;
        for(int i=1;i<l;i++){
            string t1=s.substr(0,i),t2=s.substr(i,l);
            t2+=t1;
            if(is(t2))f=1;
        }
        if(f) cout<<1<<endl;
        else cout<<2<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    linux命令-ps
    solr参数说明
    CAP原理和BASE思想
    java多线程文件上传服务器
    swift的简介
    浅谈对【OSI七层协议】的理解
    手写简易WEB服务器
    JVM知识整理和学习(转载并修改)
    多线程学习笔记六
    多线程学习笔记五
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10392599.html
Copyright © 2020-2023  润新知