EOJ Monthly 2017.12 A B C D

// 因为是中文题面就偷一次懒不写题意啦QAQ

// 各种大作业然后又要期末还不知道什么时候能补题QAQ

A. 唐纳德先生和假骰子

直接模拟

#include <bits/stdc++.h>
using namespace std;
int a[6], b[6], cnt[20];
typedef long long LL;
int main() {
    int p;
    scanf("%d", &p);
    for (int i = 0; i < 6; ++i) scanf("%d", &a[i]);
    for (int i = 0; i < 6; ++i) scanf("%d", &b[i]);
    for (int i = 0; i < 6; ++i) {
        for (int j = 0; j < 6; ++j) {
            ++cnt[(a[i]+b[j]) % p];
        }
    }
    if (p == 3) {
        if (cnt[0] == 12 && cnt[1] == 12 && cnt[2] == 12) puts("YES");
        else puts("NO");
    }
    else {
        if (cnt[0] == 9 && cnt[1]==9 && cnt[2]==9 && cnt[3]==9) puts("YES");
        else puts("NO");
    }
    return 0;
}

B. 在哈尔滨的寒风中

容易发现当棋盘大于等于(3 imes 5)时马可以到达任何地方,其他情况分类讨论一下即可。

// 一开始不知道怎么的理解成了马步只有(1 imes 2)而漏了(2 imes 1),然后整个棋局中的点就分成了四类,很高兴地交了结果wa了还纳闷的半天

// 偷懒写了个dfs(?)而没有去数小的几种情况还是原谅我吧...

#include <bits/stdc++.h>
int dr[8][2] = {{-1,-2}, {-2, -1}, {-2, 1} ,{-1, 2}, {1, 2}, {2,1}, {2,-1}, {1,-2}};
using namespace std;
typedef long long LL;
LL n,m;
int c[10][10];
LL C(LL x, int) { return x * (x-1) / 2; }
void dfs(int x, int y, int col) {
    c[x][y] = col;
    for (int i = 0; i < 8; ++i) {
        int xx = x + dr[i][0], yy = y +dr[i][1];
        if (xx <= 0 || xx > n || yy <= 0 || yy > m) continue;
        if (!c[xx][yy]) dfs(xx, yy, col);
    }
}
int cnt[100];
int main() {
    scanf("%lld%lld", &n, &m);
    LL ans=0;
    if (n > m) swap(n, m);
    if (n == 1) ans = 0;
    else if (n == 2) {
        LL n1,n2,n3,n4;
        n1=n2=n3=n4 = (n/2)*(m/2);
        if (m&1) ++n1,++n2;
        ans = C(n1,2)*2+C(n3,2)*2;
    }
    else if (n == 3 || n == 4) {
        if (m >= 5) ans = C(n*m, 2);
        else {
            int tot = 0;
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= m; ++j) {
                    if (!c[i][j]) dfs(i, j, ++tot);
                }
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= m; ++j) {
                    ++cnt[c[i][j]];
                }
            }
            for (int i = 1; i <= tot; ++i) {
                ans += C(cnt[i], 2);
            }
        }
    }
    else ans = C(n*m,2);

    printf("%lld
", ans);
    return 0;
}

C. 易位构词

按字母出现次数排个序,然后整体循环右移 (出现最多的字母出现的位数) 那么多位,然后再按下标扔回去。

很合理。

// 比赛时没做出来,一开始一直在想最大流...

// 题解还是强啊

// 注意排序的时候不仅要按次数还要按字母本身,因为目的是要让一块一块靠在一起

#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int cnt[256];
char s[maxn], ss[maxn], ans[maxn];
struct node {
    char c; int p;
    bool operator < (const node& nd) const {
        return cnt[c] > cnt[nd.c] || (cnt[c] == cnt[nd.c] && c < nd.c);
    }
}a[maxn];
int main() {
    scanf("%s", s);
    int n = strlen(s);
    for (int i = 0; i < n; ++i) a[i] = {s[i], i}, ++cnt[s[i]];
    sort(a, a+n);
    char mx = a[0].c;
    int i = 0;
    for (; i < n; ++i) if (a[i].c != mx) break;
    int num = i;
    if ((num<<1) > n) puts("impossible");
    else {
        for (int i = 0; i < n; ++i) ss[(i+num)%n] = a[i].c;
        for (int i = 0; i < n; ++i) ans[a[i].p] = ss[i];
        ans[n] = '';
        puts(ans);
    }
    return 0;
}

D. 唐纳德和他的数学老师

类似bzoj 1191 超级英雄Hero 二分图匹配

// 开这道题的时候过的才十个人出头,读了一遍下来觉得这题十分熟悉...

// 然后因为数组大小的问题RE了3发...

#include <bits/stdc++.h>
#define maxn 1010
using namespace std;
typedef long long LL;
int tot, prime[maxn], a[3010], n, match[1000010], ne[3010], pp;
bool used[1000010], check[maxn];
struct Edge {
    int to, ne;
    Edge(int _to=0, int _ne=0) : to(_to), ne(_ne) {}
}edge[3000010];
void add(int u, int v) {
    edge[tot] = Edge(v, ne[u]);
    ne[u] = tot++;
}
void init() {
    for (int i = 2; i <= 1000; ++i) {
        if (!check[i]) {
            prime[pp++] = i;
        }
        for (int j = 0; j < pp; ++j) {
            if (i * prime[j] > 1000) break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0) break;
        }
    }
}
bool find(int u) {
    for (int i = ne[u]; ~i; i = edge[i].ne) {
        int v = edge[i].to;
        if (used[v]) continue;
        used[v] = true;
        if (!match[v] || find(match[v])) {
            match[v] = u;
            return true;
        }
    }
    return false;
}
int main() {
    init();
    scanf("%d", &n);

    tot = 0; memset(ne, -1, sizeof ne);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        int temp = a[i];
        for (int j = 0; j < pp; ++j) {
            if (temp < prime[j]) break;
            if (temp % prime[j] == 0) add(i, prime[j]);
            while (temp % prime[j] == 0) temp /= prime[j];
        }
        if (temp != 1) add(i, temp);
    }
    for (int i = 1; i <= n; ++i) {
        memset(used, 0, sizeof used);
        if (!find(i)) { cout << i-1 << endl; return 0; }
    }
    cout << n << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/kkkkahlua/p/8007631.html