返回顶部

Educational Codeforces Round 92 (Rated for Div. 2)【ABCDE】(题解)

涵盖知识点:思维、数学

比赛链接:传送门

A - LCM Problem

题意: 找到一组\(x,y\)满足\(l \le x < y \le r\)\(l\le LCM(x, y) \le r\)
题解: 直接找两倍。
Accept Code:

#include <bits/stdc++.h>
using namespace std;

int main(){
    int t;cin>>t;
    while(t--){
        int l,r;
        cin>>l>>r;
        if(l*2>r)puts("-1 -1");
        else cout<<l<<" "<<l*2<<"\n";
    }
    return 0;
}

B - Array Walk

题意: 一开始在位置1,每次可以选择向右走或者向左走,但是不能连续向左走两次。问走\(k\)次,向左走不超过\(z\)次的最大权值。
题解: 暴力搜区间内最大相邻数之和。具体细节看代码就行了,不难理解。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
typedef long long ll;
int main(){
    int t;cin>>t;
    while(t--){
        int n,k,z;
        cin>>n>>k>>z;
        for(int i=0;i<n;i++)cin>>a[i];
        ll ans=0;
        k++;
        for(int i=0;i<=z;i++){
            if(k-i*2<=0)continue;
            ll sum=0;
            vector<int> v;
            for(int j=0;j<k-i*2;j++){
                v.push_back(a[j]+a[j+1]);
                sum+=a[j];
            }
            sort(v.begin(),v.end());
            reverse(v.begin(),v.end());
            sum+=v[0]*i;
            ans=max(ans,sum);
        }
        cout<<ans<<"\n";
    }
    return 0;
}

C - Good String

题意: 给定初始的\(0到9\)字符串,问最少删掉几个能使字符串左循环一单位和右循环一单位相同。
题解: 最后满足条件的串一定是全部数字都相同或者两个不同的数字依次相邻。遍历所有的情况暴力搜索一遍即可。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int t;cin>>t;
    while(t--){
        int ans=0;
        string s;
        cin>>s;
        for(int i=0;i<10;i++){
            for(int j=0;j<10;j++){
                int tmp=0;
                bool flag=false;
                for(char k : s){
                    if(!flag && k-'0'==i || flag && k-'0'==j){
                        flag=!flag;
                        tmp++;
                    }
                }
                if(i!=j) tmp=tmp/2*2;
                ans=max(ans,tmp);
            }
        }
        cout<<s.length()-ans<<"\n";
    }
}

D - Segment Intersections

题意: 初始给定两组线段,分别为\([l_1,r_1],[l_2,r_2]\),每组分别有\(n\)条线段,一一对应。规定每组的贡献值为相交区域的右区间值减去左区间值,每次操作可以使一个线段向左或向右延伸一个单位。问最少几次操作可以使得\(n\)组线段的贡献总和大于等于\(k\)
题解: 分段考虑,首先考虑初始两线段相离的情况,那么一开始的移动并不会增加贡献值,然后考虑相切后再延伸的情况下,每移动一个单位就会产生1的贡献,但是移动到重合之后,就需要两条线段同时延伸才会产生1的贡献,那么我们只要遍历所移动初始相离的情况所移动的组数然后进行贪心计算即可。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t;cin>>t;
    while(t--){
        ll n,k;
        cin>>n>>k;
        ll l1,r1,l2,r2;
        cin>>l1>>r1>>l2>>r2;
        if(l1>l2)swap(l1,l2),swap(r1,r2);
        ll s1=0,s2=0;
        if (l2>=r1)s1=l2-r1;
        ll inter=0;
        if(l2<=r1)inter=min(r1,r2)-l2;
        s2=r1-l1+r2-l2-inter*2;
        if(inter*n>=k){
            puts("0");
            continue;
        }
        if(s1&&s1>=k){
            cout<<s1+k<<"\n";
            continue;
        }
        ll ans=1e18;
        for(int i=1;i<=n;i++){
            ll cnt=0,now=inter*n;
            cnt+=i*s1*2;
            now+=i*s1;
            if(now>=k){
                ans=min(ans,cnt);
                break;
            }
            if(now+i*s2>=k){
                cnt+=k-now;
                ans=min(ans,cnt);
                continue;
            }
            cnt+=i*s2;
            now+=i*s2;
            cnt+=(k-now)*2;
            ans=min(ans,cnt);
        }
        cout<<ans<<"\n";
    }
}

E - Calendar Ambiguity

题意: 一年\(m\)个月,每个月\(d\)天,每星期\(w\)天,问有多少组\((x,y)(x<y)\)满足\(x月y日\)\(y月x日\)星期数相同。
题解: \(xd + y \equiv yd + x~(mod~w)\)推出\((x - y)(d - 1) \equiv 0~(mod~w)\),而\(d-1\)可能存在\(w\)的某些因子,所以我们将其剔除,对\(w\)除以\(gcd(w, d - 1)\)得到\(w'\)。所以,\(x-y\)只要能整除\(w'\)即可。我们假设差值为\(k\)。那么对应于每组\((x,y)\),x的最小值为\(1\),最大值应该为\(min(d, m)-k\)。而\(k\)应该是\(w'\)的倍数。所以最终答案就是\(\sum \limits_{i=1}^{min(d, m) / w'} min(d, m) - i \cdot w'\),等差数列求和即可\(O(1)\)求出。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t;cin>>t;
    while(t--){
        ll m,d,w;
        cin>>m>>d>>w;
        if(d==1){
            puts("0");
            continue;
        }
        ll g=__gcd(d-1,w);
        ll w2=w/g;
        ll mn=min(m,d);
        ll cnt=mn/w2;
        cout<<(2*(mn-w2)-w2*(cnt-1))*cnt/2<<"\n";
    }
}
posted @ 2020-07-31 23:27  Charles1999  阅读(176)  评论(0编辑  收藏  举报