1. 程式人生 > 實用技巧 >【Codeforces Round #655 (Div. 2)】A-D

【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;
}
/*

*/