【Codeforces Round #655 (Div. 2)】A-D

Codeforces Round #655 (Div. 2)

A. Omkar and Completion

题意

给出一个整数 n ,让构造出一个长度为 n 的数组,使得不存在\(1\leq x,y,z\leq n\),满足\(a_x+a_y=a_z\)

思路

直接输出 n 个 1

代码

#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n;i++){
            printf("1 ");
        }
        printf("\n");
    }
    // fuck;
    return 0;
}
/*
*/

B. Omkar and Last Class of Math

题意

给出一个整数 n ,让找出两个整数 a , b ,满足 a + b = n ,并且 LCM(a,b) 最小。

思路

先猜一下,偶数应该直接输出两个半值。

直接打了个表:

找出其最小的素因子 p ,输出 n / p , n - n / p。

代码

#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, flag = 0;
        scanf("%d", &n);
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                flag = i;
                break;
            }
        }
        if (!flag) {
            printf("%d %d\n", 1, n - 1);
        } else {
            printf("%d %d\n",n/flag, n-n/flag);
        }
    }
    // fuck;
    return 0;
}

C. Omkar and Baseball

题意

给出一个长度为 n 的全排列,现在定义一种特殊的交换:

你可以选择一个连续的子数组,任意排放其中元素的位置,只需保证每个元素都不在本来的位置。

问最少需要多少次排列使得其递增。

思路

首先可以知道最多只需要排两次。

如果本来递增,那么不需要排。

如果只有一段连续的子数组,每个元素都不在其位置上( i 不在第 i 个位置),那么只需要一次。

有两段或者多段,那么第一次选择整个数组进行打乱,第二次维护成递增

代码

#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

int arr[N];

int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        int flag = 1, num = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &arr[i]);
            if (arr[i] < arr[i - 1]) {
                flag = 0;
            }
        }
        if (flag) {
            printf("0\n");
            continue;
        }
        int pre, nex;
        for (int i = 1; i <= n; i++) {
            if (arr[i] != i) {
                pre = i;
                break;
            }
        }
        for (int i = n; i; i--) {
            if (arr[i] != i) {
                nex = i;
                break;
            }
        }
        for (int i = pre; i <= nex; i++) {
            if (arr[i] == i) {
                flag = 1;
                break;
            }
        }
        if (flag) {
            printf("2\n");
        } else
            printf("1\n");
    }
    // fuck;
    return 0;
}
/*
*/

D. Omkar and Circle

题意

给出一个长度为 n(奇数) 的循环数组(首尾相连),现在每次可以选择两个相距为 2 的数字,用他俩的和替代中间的数字。

操作到最后,只剩下一个数字,问这个数字最大是多少。

思路

本质就是删除 n / 2 个数字后最大的和。

删除的时候要满足这些数字不能相邻。

试着删一下就可以发现:

无论怎么删除都会存在两个连续的数字没有被删除,这两个数字相邻的必定被删除,其他的数字隔一个删一个。

所以我们可以枚举这两个没有被删除的数字。

维护两个数组 pre , suf 。

\(pre_i\)表示以第 i 个为结尾的隔一个删一个的被删除的和。

\(suf_i\)表示以第 i 个为开头的隔一个删一个的被删除的和。

对于以第 i , i + 1 没有被删除,其剩余的和为 \(sum - pre_i - suf_{i+2}\)

注意特判第 1 个和最后 1 个以及倒数第一个倒数第二个没被删除。

代码

#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int N = 2e5 + 10;

int arr[N];
ll pre[N], suf[N];
int main()
{
    int n;
    ll sum = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n;i++){
        scanf("%d", &arr[i]);
        sum += arr[i];
    }
    pre[1] = arr[1], suf[n] = arr[n];
    for (int i = 2; i <= n;i++){
        pre[i] = pre[i - 2] + arr[i];
    }
    for (int i = n - 1; i;i--){
        suf[i] = suf[i + 2] + arr[i];
    }
    ll ans = inf;
    for (int i = 1; i < n - 1; i++) {
        ans = min(ans, pre[i - 1] + suf[i + 2]);
    }
    ans = min(min(pre[n - 1], pre[n - 2]), ans);
    printf("%lld\n", sum - ans);
    // fuck;
    return 0;
}
/*

*/
posted @ 2020-08-01 09:52  Valk3  阅读(75)  评论(0编辑  收藏  举报