Codeforces Educational Round 12 655ABCDE

Codeforces Educational Round 12
通过数: 3
A:
刚开始用公式分类讨论,后面发现暴力才是一种更优美的解法

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 10 + 5;
char str[MAXN];
int main()
{
    int x1, y1, x2, y2;
    while(scanf("%d%d%d%d", &x1, &y1, &x2, &y2) != EOF) {
        scanf("%s", str);
        int st = ((str[0] - '0') * 10 + (str[1] - '0')) * 60 + (str[3] - '0') * 10 + str[4] - '0';
        int en = st + y1;
        int ans = 0;
        int now = 300;
        while(now < 1440) {
            if(now + y2 > st && now < en) ans++;
            now += x2;
        }
        printf("%d\n", ans);
    }
    return 0;
}

B:
暴力模拟

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100 + 5;
int id[MAXN];
int pos[MAXN];
int n, m, l;
int remov(int mark)
{
    int res = id[mark];
    for(int i = res ; i >= 2 ; i--) {
        pos[i] = pos[i - 1];
        id[pos[i]] = i;
    }
    pos[1] = mark;
    id[mark] = 1;
    return res;
}
int main()
{
    while(scanf("%d%d%d", &n, &m, &l) != EOF) {
        for(int i = 1 ; i <= l ; i++) {
            int u; scanf("%d", &u);
            pos[i] = u; id[u] = i;
        }
        int ans = 0;
        for(int i = 1 ; i <= n ; i++) {
            for(int j = 1 ; j <= m ; j++) {
                int u; scanf("%d", &u);
                int temp = remov(u);
//                printf("i = %d, j = %d, temp = %d\n", i, j, temp);
//                for(int k = 1 ; k <= l ; k++) printf("%d ", pos[k]);
//                puts("");
//                system("pause");
                ans += temp;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

C:
连续相同的一段贪心的变换一下就可以

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
char str[MAXN];
int main()
{
    while(scanf("%s", str) != EOF) {
        int len = strlen(str);
        int now = 0;
        for(int i = 1 ; i < len ; i++) {
            if(str[i] == str[now]) continue;
            else {
//                printf("i = %d, now = %d\n", i, now);
                for(int j = now + 1 ; j <= i - 1 ; j += 2) {
                    for(int k = 0 ; k < 26 ; k++) {
//                        printf("j = %d, k = %d\n", j, k);
                        if(j > 0 && str[j - 1] - 'a' == k) continue;
                        if(j < len - 1 && str[j + 1] - 'a' == k) continue;
                        str[j] = k + 'a';
                        break;
                    }
                }
                now = i;
            }
        }
        int i = len;
        for(int j = now + 1 ; j <= i - 1 ; j += 2) {
            for(int k = 0 ; k < 26 ; k++) {
//                     printf("j = %d, k = %d\n", j, k);
                if(j > 0 && str[j - 1] - 'a' == k) continue;
                if(j < len - 1 && str[j + 1] - 'a' == k) continue;
                str[j] = k + 'a';
                break;
            }
        }
        cout << str << endl;
    }
    return 0;
}

D:
/*
子集的组成只可能有两种
一种是1,和一个合法的非1数
一种是两个合法的非1数

可以用奇数偶数分类的办法证明不可能存在三个合法的非1数

*/

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 5;
bool prime[MAXN];
void init()
{
    for(int i = 0 ; i < MAXN ; i++) prime[i] = true;
    prime[0] = prime[1] = false;
    for(int i = 2 ; i < MAXN ; i++) {
        if(prime[i] == false) continue;
        for(int j = i + i ; j < MAXN ; j += i)
             prime[j] = false;
    }
}
int n;
struct Node
{
    int u, id;
}a[1000 + 5];
bool cmp(Node a, Node b) {return a.u < b.u;}
int main()
{
    init();
    while(scanf("%d", &n) != EOF) {
        for(int i = 1 ; i <= n ; i++) scanf("%d", &a[i].u), a[i].id = i;
//        puts("zero");
        sort(a + 1, a + 1 + n, cmp);
//        puts("zero2");
        int mark = n + 1;
        int zeronum = 0;
        for(int i = 1 ; i <= n ; i++) {
            if(a[i].u != 1) {
                mark = i;
                break;
            }
            else zeronum++;
        }
        int ans1 = zeronum;
        int re = -1;
        for(int i = mark ; i <= n ; i++) if(prime[1 + a[i].u]) {ans1++; re = a[i].u; break;}
//        puts("first");
        int ans2 = 0;
        int re2, re3;
        re2 = re3 = -1;
        for(int i = mark ; i <= n ; i++) {
            for(int j = i + 1 ; j <= n ; j++) {
                if(prime[a[i].u + a[j].u]) {
                    ans2 = 2;
                    re2 = a[i].u, re3 = a[j].u;
                }
            }
        }
//        puts("second");
        int ans3 = 1;
        if(ans1 >= ans2 && ans1 >= ans3) {
            printf("%d\n", ans1);
            int f = 1;
            for(int i = 1 ; i < ans1 ; i++) printf("%d ", 1);
            if(re != -1) printf("%d", re);
            else printf("%d", 1);
            puts("");
        }
        else if(ans2 >= ans1 && ans2 >= ans3) {
            printf("%d\n", ans2);
            printf("%d %d\n", re2, re3);
        }
        else {
            printf("%d\n%d\n", ans3, a[1].u);
        }
    }
    return 0;
}

E:
/*
存一个之前所有数的异或和
由异或和的性质知道sum[l,r] = sum[1,l - 1] ^ sum[1,r]

然后用字典树存储这个异或和的二进制表示
每次查询后插入即可

*/

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAX = 31;
const int MAXN = 1e6 + 5;
const int MAXM = MAX * MAXN;
int num[MAXM];
int ne[MAXM][2];
int cnt;
int n, k;
string toS(int u)
{
    string str = "";
    while(u) {
        if(u & 1) str += '1';
        else str += '0';
        u /= 2;
    }
    while(str.size() < MAX - 1) str += '0';
    reverse(str.begin(), str.end());
    return str;
}
int query(string str, string st)
{
    int now = 0;
    int ans = 0;
    int mark = 0;
    while(now < str.size() && mark != -1) {
        if(str[now] == '0' && st[now] == '0') {
            if(ne[mark][1] != -1) ans += num[ne[mark][1]];
            mark = ne[mark][0];
        }
        else if(str[now] == '0' && st[now] == '1') {
            mark = ne[mark][1];
        }
        else if(str[now] == '1' && st[now] == '0') {
            if(ne[mark][0] != -1) ans += num[ne[mark][0]];
            mark = ne[mark][1];
        }
        else if(str[now] == '1' && st[now] == '1') {
            mark = ne[mark][0];
        }
        now++;
    }
    if(mark != -1)
        ans += num[mark];
    return ans;
}
void ins(string str)
{
    int u = 0;
    for(int i = 0 ; i < str.size() ; i++) {
        int j = str[i] - '0';
        if(ne[u][j] == -1) ne[u][j] = ++cnt;
        num[u]++;
//        printf("%d ", u);
        u = ne[u][j];
    }
    num[u]++;
//    puts("");
}
int main()
{
    while(scanf("%d%d", &n, &k) != EOF) {
        memset(num, 0, sizeof num);
        memset(ne, -1, sizeof ne);
        long long ans = 0;
        cnt = 0;
        int sum = 0;
        string st = toS(k);
        for(int i = 0 ; i <= n ; i++) {
            int u;
            if(i > 0)
                scanf("%d", &u);
            else u = 0;
            u = u ^ sum;
            string str = toS(u);
            int temp = query(str, st);
//            printf("i = %d, temp = %d, u = %d\n", i, temp, u);
//            cout << str << endl;
            ans = ans + temp;
//            cout << str << endl;
            ins(str);
            sum = u;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值