Codeforces Round #726 (Div. 2)

传送门

A. Arithmetic Array

代码

#include <iostream>
using namespace std;
int main() {
    int T;
    cin>>T;
    while(T--) {
        int n;
        cin>>n;
        int sum=0;
        for(int i=1;i<=n;++i) {
            int x;
            cin>>x;
            sum+=x;
        }
        if(sum==n) cout<<0<<endl;
        else if(sum<n) cout<<1<<endl;
        else cout<<sum-n<<endl;
    }
}

B. Bad Boy

题解

最大可以让这个人走 n + n + m + m − 4 n+n+m+m-4 n+n+m+m4

代码

#include <iostream>
using namespace std;
int main() {
    int T;
    cin >> T;
    while(T--) {
        int n, m, i, j;
        cin >> n >> m >> i >> j;
        cout<< 1 << ' ' << 1 << ' ' << n << ' '<< m <<endl;
    }
    return 0;
}

C. Challenging Cliffs

题解

找到任意一对绝对值最小的数 ( i , i + 1 ) (i,i+1) (i,i+1),这样满足第一个条件最优。
原本升序输出可以得 n − 1 n-1 n1分,但是 ( i , i + 1 ) (i,i+1) (i,i+1)被分开,最多可以得 n − 2 n-2 n2
答案输出 a [ i + 1... n ] a [ 1... i ] a[i+1...n] a[1...i] a[i+1...n]a[1...i]
(读错题,wa了一辈子)

代码

#include <iostream>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
const int N=200010;
int a[N];
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        int n, tot = 0, num = 0;
        scanf("%d",&n);
        for(int i = 1; i <= n; ++ i) scanf("%d",&a[i]);
        sort(a + 1,a + 1 + n);
        if(n > 2) {
            int sub = 1e9, ii;
            for(int i = 1;i < n; ++ i) {
                if(a[i + 1] - a[i] < sub) sub = a[i + 1] - a[i], ii = i;
            }
            for(int i = ii + 1; i <= n; ++ i) cout << a[i] << ' ';
            for(int i = 1; i <= ii; ++ i) cout << a[i] << ' ';
        }
        else {
            for(int i = 1; i <= n; ++ i) cout << a[i] << ' ';
        }
        cout << endl;
    }
    return 0;
}

D. Deleting Divisors

题解

打表找规律。
n n n是奇数 Bob赢
n n n是偶数 且不是 2 2 2的幂次 Alice赢
n n n是偶数 且是 2 2 2的幂次 如果 l o g 2 ( n ) log2(n) log2(n)是奇数 Bob赢 否则 Alice赢

代码

#include <iostream>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;
const int N=10000010;
int f[N][2];
/*打表代码*/
int dfs(int x,int y) { 
    if(f[x][y]!=-1) return f[x][y];
    f[x][y]=0;
    for(int j=2;j*j<=x;++j) {
        if(x%j==0) {
            int k=x/j;
            if(!dfs(x-j,1-y)) f[x][y]=1;
            if(!dfs(x-k,1-y)) f[x][y]=1;
        }
    }
    return f[x][y];
}
int main() {
    int T;
    cin>>T;
    // for(int i=0;i<N;++i) f[i][0]=f[i][1]=-1;
    // for(int i=1;i<199;++i) {
    //     if(dfs(i,0));
    //     else if(i%2==0) cout<<i<<endl;
    // }
    while(T--) {
        int n;
        cin>>n;
        if(n%2) puts("Bob");
        else {
            int ans=-1;
            for(int i=1;i<=30;++i) {
                if(n==(1<<i) ) {
                    ans=i;
                    break;
                }
            }
            if(ans!=-1) {
                if(ans%2==0) puts("Alice");
                else puts("Bob");
            }
            else puts("Alice");
        }
    }
    return 0;
}

E1. Erase and Extend (Easy Version)

题解

首先确定一种策略,先将 s s s删除变成成 s ′ s' s,然后复制s’再将多余 k k k的字母删除。问题就是如果得到 s ′ s' s.
e 1 e1 e1可以 O ( n 2 ) O(n^2) O(n2)枚举。
还有一个单调性,如果 s [ 1 , l e n ] + s [ 1 , l e n ] + . . . < s [ 1 , n + s [ 1 , n ] + . . . s[1,len]+s[1,len]+...<s[1,n+s[1,n]+... s[1,len]+s[1,len]+...<s[1,n+s[1,n]+...,那么有 s [ 1 , l e n ] + s [ 1 , l e n ] + . . . < s [ 1 , i ] + s [ 1 , i ] + . . . s[1,len]+s[1,len]+...<s[1,i]+s[1,i]+... s[1,len]+s[1,len]+...<s[1,i]+s[1,i]+...对于所有 l e n < i len<i len<i (不确定)
如果要 s ′ = s [ 1... l e n ] s'=s[1...len] s=s[1...len],就有 s [ l e n + 1.. n ] + s > s [ 1.. n ] s[len+1..n]+s>s[1..n] s[len+1..n]+s>s[1..n],kmp预处理 s [ i ] s[i] s[i] n e x t next next数组,从前向后枚举要删除包括 i i i,最小的删除下标是多少, j = n e [ i − 1 ] + 1 j=ne[i-1]+1 j=ne[i1]+1,比较 s [ j ] s[j] s[j] s [ j ] s[j] s[j],也就是比较 s [ 1... j ] s[1...j] s[1...j] s [ i − j + 1... i ] s[i-j+1...i] s[ij+1...i]的大小。

代码

#include <iostream>

using namespace std;

const int N = 5010;
int n, k;
char str[N];
bool cmp(int x,int y) {
    int i = 1, j = 1, t = k;
    while(--t) {
        if(str[i] < str[j]) return true;
        if(str[i] > str[j]) return false;
        ++i , ++j;
        if(i > x) i = 1;
        if(j > y) j = 1;
    }
    return true;
}
int main() {
    cin >> n >> k;
    cin >> (str+1);
    int len = n;
    for (int i = n; i >= 1; --i) {
        if(cmp(i,len)) {
            len = i;
        }
    }
    for(int i = 1, j=1; i <= k; ++i) {
        cout << str[j];
        if(++j > len) j=1;
    }
}

E2. Erase and Extend (Hard Version)

代码

#include <iostream>

using namespace std;

const int N = 500010;
int n, k, ne[N];
char str[N];
int main() {
    cin >> n >> k;
    cin >> (str + 1);
    for(int i = 1; i <= n; ++ i) str[i + n] = str[i];
    for(int i = 2, j = 0; i <= n*2; ++ i) {
        while (j && str[i] != str[j + 1] ) j = ne[j];
        if( str[i] == str[j + 1]) ++ j;
        ne[i] = j;
    }

    int len = n;
    for(int i = 1; i <= n * 2; ++i) {
        int j = ne[i - 1] + 1;
        if( str[j] < str[i] ) {
            cout<<i<<' '<<j<<endl;
            len = i - j;
            break;
        }
    }
    for(int i = 1, j=1; i <= k; ++i) {
        cout << str[j];
        if(++j > len) j=1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值