codeforces round 209

A:水

直接观察得到只有两种情况,要么2次,要么4次,如果边界上有1则为2次,否则为4次

AC代码:

#include <cstdio>
#include <cstring>


const int MAX_NUMBER = 55;


int maps[MAX_NUMBER][MAX_NUMBER];
int n, m;

int main() {

    scanf("%d%d", &n, &m);
    int flag = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &maps[i][j]);
            if (maps[i][j]) {
                if (i == 1 || i == n) {
                    flag = 1;
                }
                if (j == 1 || j == m) {
                    flag = 1;
                }
            }
        }
    }
    if (flag) {
        printf("2\n");
    }
    else {
        printf("4\n");
    }
    return 0;
}


B题

n很大,首先发现1 2 3 4 5 6 ... n的排列根据他所给的函数算出来为0.

所以k = 0的时候直接就是1 2 3 4 5 6 ..n

然后前面绝对值是奇数-偶数的绝对值的和,后面是奇数和-偶数和的绝对值

所以我把1 2 3 4 ... n换成 2 1 .... n,前面的和不变为n

后面的和变为n - 2,所以算出来为2,交换一对多2,现在要多2k,交换k对即可

#include <cstdio>
#include <cstring>

const int MAX_NUMBER = 100007;
int n, k;
int main() {

    scanf("%d%d", &n, &k);
    n *= 2;
    k *= 2;
    int number = k / 2;
    int first = 1;
    for (int i = 1; i <= n; i += 2) {
        if (number) {
            if (first) {
                printf("%d %d", i + 1, i);
                first = 0;
            }
            else {
                printf(" %d %d", i + 1, i);
            }
            number--;
        }
        else {
            if (first) {
                printf("%d %d", i, i + 1);
                first = 0;
            }
            else {
                printf(" %d %d", i, i + 1);
            }
        }
    }
    printf("\n");
    return 0;
}


3:求最大公约数mod 10^9 + 7

首先用gcd求是肯定不行的,然后发现分母为x ^ (a1 + a2 + ... +an)

分子为x^(a1 + a2 + .. + an-1) + x ^ (a2 + a3 + .. + an) + ....每个x次数为a1 + a2 + ...+ an中去除一项

所以很明显可以约的数一定有x ^ (aa + a2 + a3 + ... + an-1).因为a1,a2,a3...an是递增的,所以a1+a2+a3+..+an-1次数最小

约掉这个公约数是后分母为x^an

分为为 x ^ (an - an) + x^(an - an-1) + x^(an - an-2) + ... + x(an - a1)

然后可能还有公约数x,最小数为x^(an - an),为1,看有多少个1,可能这么多个1加起来还为x的倍数,所以要继续约去x,约去x之后同样多个1加起来仍然和分母x^an有公因数。

一直暴力约去。

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const long long MOD_NUMBER = 1000 * 1000 * 1000 + 7;
const int MAX_NUMBER = 100006;

long long value[MAX_NUMBER];
int vis[MAX_NUMBER];

long long getMod(long long number, long long power) {
    if (power == 0) {
        return 1;
    }
    long long x = getMod(number, power / 2);
    x = (x * x) % MOD_NUMBER;
    if (power % 2) {
        x = (x * number) % MOD_NUMBER;
    }
    return x;
}
long long x, n;

int getPower(int number) {
    int i = 1;
    while (number % x == 0) {
        i++;
        number /= x;
    }
    i--;
    return i;
}
int main() {

    cin >> n >> x;
    memset(vis, 0, sizeof(vis));
    long long sums_1 = 0;
    for (int i = 1; i <= n; i++) {
        cin >> value[i];
        if (i != n) {
            sums_1 += value[i];
        }
    }
    long long max_n = value[n];
    long long ans = getMod(x, sums_1);
    int equal = 0;
    for (int i = n; i >= 1; i--) {
        value[i] = max_n - value[i];
        if (value[i] == 0) {
            equal++;
            vis[i] = 1;
        }
    }
    while ((equal % x) == 0 && max_n > 0) {
        ans = (ans * x) % MOD_NUMBER;
        equal /= x;
        max_n--;
        for (int i = 1; i <= n; i++) {
            if (!vis[i]) {
                value[i]--;
                if (value[i] == 0) {
                    equal++;
                    vis[i] = 1;
                }
            }
        }
    }
    cout << ans << endl;
    return 0;
}

D:

DP.

left_loc[i]表示value[i]作为约数,最左可以扩展的范围,如果value[i - 1] % value[i] == 0,那么扩展value[i - 1]即可。而value[i - 1]已经向左扩展好了。

同理right_loc[i]。然后求出答案

AC代码:

#include <cstdio>
#include <cstring>
#include <set>
#include <iostream>

using namespace std;

const int MAX_NUMBER = 300006;

int left_loc[MAX_NUMBER];
int right_loc[MAX_NUMBER];
int value[MAX_NUMBER];
int n;
set<int> ans;
int main() {

    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &value[i]);
    }
    left_loc[1] = 1;
    for (int i = 2; i <= n; i++) {
        int j = i;
        while (j != 1 && (value[j - 1] % value[i]) == 0) {
            j = left_loc[j - 1];
        }
        left_loc[i] = j;
    }
    right_loc[n] = n;
    for (int i = n - 1; i >= 1; i--) {
        int j = i;
        while (j != n && (value[j + 1] % value[i]) == 0) {
            j = right_loc[j + 1];
        }
        right_loc[i] = j;
    }
    int max_number = 0;
    ans.clear();
    for (int i = 1; i<= n; i++) {
        max_number = max(max_number, right_loc[i] - left_loc[i]);
    }
    for (int i = 1; i <= n; i++) {
        if (right_loc[i] - left_loc[i] == max_number) {
            ans.insert(left_loc[i]);
        }
    }
    cout << ans.size() << " " << max_number << endl;
    for (set<int>::iterator it = ans.begin(); it != ans.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值