Codeforces Round #655 Div2题解

A.Omkar and Completion

题目描述

要求你找出一个序列a,满足序列a对于任意的x,y,z都满足:
a x + a y ≠ a z a_x + a_y ≠ a_z ax+ay=az
并且满足ai <= 1000

题解:

一开始我还想打个奇数表啥的…

但是看见元素值要求小于1000就放弃了,因为第1000大的奇数早就爆了…

其实这个题很简单,都是1不就好了QAQ

AC代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5;
int a[maxn] = {};
int main()
{
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        for(int i = 1;i < n;i++) cout << "1 ";
        cout << 1 << endl;
    }
    return 0;
}

B.Omkar and Last Class of Math

题目描述:

给定一个数n,要求找出两个正整数满足
a + b = n a + b = n a+b=n

L C M ( a , b ) − > m i n LCM(a,b) -> min LCM(a,b)>min
题解:

首先我们知道的是,lcm的值最小就是a,b,其中之一,那么我们就去找b是a的倍数的情况。那么我们可以得到,a就是n的倍数
a = x ; b = k x ; a + b = n 则 有 n = K x a = x; b = kx; a + b = n则有n = Kx a=x;b=kx;a+b=nn=Kx
所以我们需要枚举一下n的倍数,而且要求lcm的值最小其实就是要求a的值尽可能大,最大不会超过n/2(O(n)),所以枚举一下答案就可以

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
    int t,a = 1,b;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        a = 1;
        b = n - 1;
        for(int i = 2;i <= sqrt(n);i++){ //注意这里枚举的其实是上面说的K的值
            if(n % i == 0){
                a = n/i;
                b = n - n/i;
                break;
            }
        }
        cout << a << ' ' << b << endl;
    }   
    return 0;
}

C.Omkar and Baseball

题目描述:

给你一个随机序列a,现在规定一种排序方法:对于任意区间内的元素,我们可以对他们进行重新排序,但是要求每个元素都不能在他之前的位置上,现在问对于一个随机序列,你需要做几次这样的操作才能实现序列有序(规定为升序)?

题解:

这个题目我们可以这样考虑:

对于一个序列而言,如果该元素的位置是正确的,那么我们就不需要对它进行重新排序了,所以这个问题转化为:找这个序列中所有的不连续的错排序列,这样最后找出来的连续错排序列就是答案了。

AC题解:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 2e5 + 19;
int a[maxn] = {};
int main()
{
    int t;
    cin >> t;
    while(t--){
        memset(a,0,sizeof(a));
        int n,sum = 0;
        cin >> n;
        for(int i = 1;i <= n;i++) cin >> a[i];
        for(int i = 1;i <= n;i++) //连续不正确序列数目
            if(a[i] != i && a[i - 1] == i - 1) sum++;
        if(sum >= 2) cout << 2 << endl;
        else cout << sum << endl;
    }
    return 0;
}

D.Omkar and Circle

题目描述:

给出一个环形,现在可以将与某一个数相邻的两个数相加后来代替这个数,一直操作到这个环中还剩下一个数,现在问你最后得到的最大值可以是多少。

题解:

我们分析一下这个操作:

把一个数替换成它的两边的数之和,其实就是每一次减去一个数,而且这些数不能相邻,问最后剩下的元素和最大会是多少。

所以我们可以维护每个元素的不相邻的前缀和后缀和,最后找到二者相加最大的值就是最后答案。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int maxn = 2e5 + 19;
ll a[maxn] = {},b[maxn] = {},c[maxn] = {};
int main()
{
    int n,cnt = 0,num;
    cin >> n;
    num = n;
    for(int i = 1;i <= n;i++) cin >> a[i];
    for(int i = 1;i <= n;i++){ //统计前缀和
        if(i <= 2) b[++cnt] = a[i];
        else b[++cnt] = a[i] + b[i - 2]; 
    }
    for(int i = n;i >= 1;i--){ //统计后缀和
        if(i >= n - 1) c[num--] = a[i];
        else c[num--] = a[i] + c[i + 2];
    }
    ll ans = 0;
    for(int i = 1;i <= n;i++){ //找最大
        ans = max(ans,b[i] + c[i + 1]); //当前元素的前缀加后一个元素的后缀
    }
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CUCKyrie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值