Codeforces Round #324 (Div. 2) A B C D E

A,水题不多说。

#include<bits/stdc++.h>
using namespace std;

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int n,t; scanf("%d%d",&n,&t);
    if(t<10){
        for(int i = n; i--;) putchar('0'+t);
    }else{
        if(n == 1) puts("-1");
        else{
            putchar('1');
            for(int i = n; --i;) putchar('0');
        }
    }
    return 0;
}
A

B,用补集算一下。

#include<bits/stdc++.h>
using namespace std;

const int mod = 1e9+7;
typedef long long ll;
int qpow(int a,int q)
{
    int re = 1;
    while(q){
        if(q&1) re = (ll)re*a%mod;
        a = (ll)a*a%mod;
        q >>= 1;
    }
    return re;
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int n; scanf("%d",&n);
    int ans = (qpow(27,n)-qpow(7,n)+mod)%mod;
    printf("%d",ans);
    return 0;
}
B

C,当s1[i] != s2[i]的时候至少其中f值+1,效果记为10,01,11(与s1[i]和s2[i]都不同)

s1[i] == s2[i]的时候效果记为11 00。

记s[i] != s[i]有ct1个,为了保证两个f相等如果ct是奇数,单出来那个只有使得f1,f2同时加1,所以下界为low = (ct+1)/2。

其中有ct/2个对10,01 。当t<low的时候无解。

记s1[i]==s2[i]有ct2 = n-ct1个,当t>=low && t <= low+ct2的时候,只要在s1[i]==s2[i]时取相应个数个的ch,ch !=s1[i]。(11)

当t>=low+ct2的时候,需要从ct/2对中选出一些来变成 11,11

#include<bits/stdc++.h>
using namespace std;

const int LEN = 1e5+5;
char s[2][LEN];

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int n,t; scanf("%d%d
",&n,&t);
    gets(s[0]); gets(s[1]);
    int ct1 = 0;
    for(int i = 0; i < n; i++){
        ct1 += s[0][i] == s[1][i];
    }
    int ct2 = n-ct1;
    int low = (ct2+1)/2;
    if(t < low){
        puts("-1");
    }else {
        int pir = low - (ct2&1);
        int del = t - low - ct1;
        int swc = 0, ct, ex;
        if(del > 0) {
            ex = ct1;
            ct = (pir - del)*2;
        }else {
            ct = (pir)*2;
            ex = t - low;
        }
        for(int i = 0; i < n; i++){
            if(s[0][i] != s[1][i]){
                if(ct){ //控制 01
                    ct--;
                    putchar(s[swc ^= 1][i]);
                }else {
                    for(char c = 'a'; c <= 'z'; c++){
                        if(c != s[0][i] && c != s[1][i]) {
                            putchar(c); break;
                        }
                    }
                }
            }else {
                if(ex){ //控制11
                    ex--;
                    for(char c = 'a'; c <= 'z'; c++){
                        if(c != s[0][i] && c != s[1][i]) {
                            putchar(c); break;
                        }
                    }
                }else {
                    putchar(s[0][i]);
                }
            }
        }
    }
    return 0;
}
C

D,暴力,有个事实是1e9以内的的素数间隔不超过282,sqrt(N)判断一下就好了。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;
int Prim[maxn], sz ;
bool vis[maxn];
void seive(int n = maxn-5)
{
    int m = (int)sqrt(n+0.5);
    for(int i = 2; i <= m; i++){
        if(!vis[i])
        for(int j = i*i; j <= n; j += i){
            vis[j] = true;
        }
    }
    for(int i = 2; i <= n; i++){
        if(!vis[i]) Prim[sz++] = i;
    }
}

bool chkPrime(int x)
{
    int m = (int)sqrt(x+0.5);
    for(int i = 0; Prim[i] <= m; i++){
        if(x%Prim[i] == 0) return false;
    }
    return true;
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    seive();
    int n; scanf("%d",&n);
    if(chkPrime(n)){
        puts("1");
        printf("%d",n);
    }else if(chkPrime(n-2)){
        puts("2");
        printf("%d %d",2,n-2);
    }else {
        puts("3");
        for(int i = 4; ; i += 2){
            if(chkPrime(n-i)){
                printf("%d ",n-i);
                n = i;
                break;
            }
        }
        for(int i = 0; Prim[i] <= n; i++){
            if(chkPrime(n-Prim[i])){
                printf("%d %d",Prim[i],n-Prim[i]);
                break;
            }
        }
    }
    return 0;
}
D

E,问交换的最小花费。看成一个置换环,最优的交换就是不断消去端点,但是这样不太好写。

一般两个排列问相对关系都可以把其中一个做映射会方便处理。把序列b映射成1...n,把a按照相同规则映射,并记录映射后元素x的位置。

从小的元素枚举,找到它在序列中的位置p[x],小的要往左边走,判断一下左边的元素是不是要往大于p[x]的位置走。如果是就交换。

p[x]的位置前面一定会有一个不小于p[x]的元素。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 2001;
int mp[maxn];
int a[maxn],p[maxn];

#define PB push_back
#define MP make_pair
#define fi first
#define se second


//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int n; scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        scanf("%d",a+i);
    }
    for(int i = 1; i <= n; i++){
        int x; scanf("%d",&x);
        mp[x] = i;
    }
    for(int i = 1; i <= n; i++){
        p[ a[i] = mp[a[i]] ] = i;
    }

    int c = 0;
    for(int x = 1; x <= n; x++){
        for(int j = p[x]; --j>=x ; ){
            if(a[j] >= p[x]){
                c += p[x] - j;
                swap(a[j],a[p[x]]);
                ans.PB(MP(j,p[x]));
                p[a[j]] = p[x];
                p[x] = j;
            }
        }
    }

    printf("%d
",c);
    printf("%d
",(int)ans.size());
    for(auto i: ans){
        printf("%d %d
",i.fi,i.se);
    }
    return 0;
}
E
原文地址:https://www.cnblogs.com/jerryRey/p/4859507.html