Codeforces Round #369 (Div. 2) ABCDE题解

来源:互联网 发布:pfx转jks linux 编辑:程序博客网 时间:2024/05/17 10:03

A. Bus to Udayland

水题,枚举字符并判断,无坑点

#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 1e3 + 50;const int MAXM = 5e3 + 50;int n, m;char s[MAXN][10];int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d", &n)) {        bool ok = false;        for (int i = 0; i < n; i++) {            scanf("%s", s[i]);            if (!ok) {                if (s[i][0] == 'O' && s[i][1] == 'O') {                    s[i][0] = s[i][1] = '+';                    ok = true;                }                if (!ok) {                    if (s[i][3] == 'O' && s[i][4] == 'O') {                        s[i][3] = s[i][4] = '+';                        ok = true;                    }                }            }        }        if (!ok)            puts("NO");        else {            puts("YES");            for (int i = 0; i < n; i++)                printf("%s\n", s[i]);        }    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}



B. Chris and Magic Square

水题,先记录0出现的位置,然后用已知的行和,求出应该填写的数,再判断是否相等。注意要特判n=1的情况。

#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 500 + 50;const int MAXM = 5e3 + 50;int n, num[MAXN][MAXN];LL c[MAXN], r[MAXN], d1, d2;int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d", &n)) {        memset(c, 0, sizeof(c));        memset(r, 0, sizeof(r));        d1 = d2 = 0;        int x, y;        for (int i = 0; i < n; i++) {            for (int j = 0; j < n; j++) {                scanf("%d", &num[i][j]);                if (num[i][j] == 0) {                    x = i; y = j;                    continue;                }                r[i] += num[i][j];                c[j] += num[i][j];                if (i == j) d1 += num[i][j];                if (i + j == n - 1) d2 += num[i][j];            }        }        if (n == 1) {            puts("1");            continue;        }        LL ans = 0;        if (x > 0)            ans = r[x - 1] - r[x];        else            ans = r[x + 1] - r[x];        r[x] += ans;        c[y] += ans;        if (x == y)            d1 += ans;        if (x + y == n - 1)            d2 += ans;        bool ok = true;        LL flag = r[0];        for (int i = 0; i < n; i++) {            if (r[i] != flag || c[i] != flag) {                ok = false;                break;            }        }        if (d1 != flag || d2 != flag)            ok = false;        if (!ok || ans <= 0)            puts("-1");        else            printf("%I64d\n", ans);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}


C. Coloring Trees

简单dp,dp[i][j][k]表示第i个位置,颜色为j,段数为k的最小花费。我比较蠢- -,分了4种情况(当前位置和上一个位置是否为0)讨论(比赛时有个细节写错了结果fst。状态转移方程见代码。时间复杂度是O(n*m^2*k),用cf的测评机跑不会超时。

#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 100 + 50;const int MAXM = 5e3 + 50;int n, m, k, c[MAXN], cost[MAXN][MAXN];LL dp[MAXN][MAXN][MAXN];int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d%d%d", &n, &m, &k)) {        memset(dp, INFLL, sizeof(dp));        memset(cost, 0, sizeof(cost));        for (int i = 1; i <= n; i++)            scanf("%d", &c[i]);        if (!c[1])            c[0] = 101;        else            c[0] = c[1];        for (int i = 1; i <= n; i++) {            for (int j = 1; j <= m; j++) {                scanf("%d", &cost[i][j]);            }        }        for (int i = 1; i <= m; i++) {            dp[0][i][0] = 0;        }        for (int i = 1; i <= m; i++) {            if (c[1])                dp[1][c[1]][1] = 0;            else                dp[1][i][1] = cost[1][i];        }        for (int i = 1; i <= n; i++) {            if (c[i]) {                if (c[i - 1]) {                    for (int l = 1; l < i; l++) {                        if (c[i] == c[i - 1])                            dp[i][c[i]][l] = min(dp[i][c[i]][l], dp[i - 1][c[i - 1]][l]);                        else                            dp[i][c[i]][l + 1] = min(dp[i][c[i]][l + 1], dp[i - 1][c[i - 1]][l]);                    }                } else {                    for (int j = 1; j <= m; j++) {                        for (int l = 1; l < i; l++) {                            if (c[i] == j)                                dp[i][j][l] = min(dp[i][j][l], dp[i - 1][j][l]);                            else                                dp[i][c[i]][l + 1] = min(dp[i][c[i]][l + 1], dp[i - 1][j][l]);                        }                    }                }            } else {                if (c[i - 1]) {                    for (int j = 1; j <= m; j++) {                        for (int l = 1; l < i; l++) {                            if (j == c[i - 1])                                dp[i][j][l] = min(dp[i][j][l], dp[i - 1][j][l] + cost[i][j]);                            else                                dp[i][j][l + 1] = min(dp[i][j][l + 1], dp[i - 1][c[i - 1]][l] + cost[i][j]);                        }                    }                } else {                    for (int j1 = 1; j1 <= m; j1++) {                        for (int j2 = 1; j2 <= m; j2++) {                            for (int l = 1; l < i; l++) {                                if (j1 == j2)                                    dp[i][j1][l] = min(dp[i][j1][l], dp[i - 1][j1][l] + cost[i][j1]);                                else                                    dp[i][j1][l + 1] = min(dp[i][j1][l + 1], dp[i - 1][j2][l] + cost[i][j1]);                            }                        }                    }                }            }        }        LL ans = INFLL;        if (c[n])            ans = min(ans, dp[n][c[n]][k]);        else            for (int i = 1; i <= m; i++) {                ans = min(ans, dp[n][i][k]);            }        printf("%I64d\n", ans == INFLL ? -1 : ans);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}


D. Directed Roads

简单图论+计数。(qwb说的对,确实是水题

题目意思是给你一个可能有环的有向图,你可以翻转一些边(原来u->v变成v->u),使得原图变为一个DAG,输出方案数。

思路比较直接,跑一遍tarjan统计出每个强连通分量的节点数,对于节点数num>2的强连通分量来说,我们必须翻转其中的[1,num-1](也就是(2^num)-2)条边。然后对于其余强连通分量(也就是不属于num>2的scc的节点),我们可选可不选,也就是有2^tmp种情况。然后把以上两种情况的所有结果相乘即可。

#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 2e5 + 50;const int MAXM = 2e5 + 50;int n;struct edge {    int to, nxt;} E[MAXM];int Head[MAXN], tot;void edge_init() {    tot = 0;    memset(Head, -1, sizeof(Head));}void edge_add(int u, int v) {    E[tot].to = v;    E[tot].nxt = Head[u];    Head[u] = tot++;}/*for (int i = 1; i <= n; i++)    if (!DFN[i])        Tarjan(i);*/int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN], num[MAXN];int Index, top, scc;bool InStack[MAXN];void Tarjan_init() {    memset(DFN, 0, sizeof(DFN));    memset(num, 0, sizeof(num));    memset(InStack, false, sizeof(InStack));    Index = scc = top = 0;}void Tarjan(int u) {    int v;    Low[u] = DFN[u] = ++Index;    Stack[top++] = u;    InStack[u] = true;    for(int i = Head[u]; i != -1; i = E[i].nxt) {        v = E[i].to;        if( !DFN[v] ) {            Tarjan(v);            if( Low[u] > Low[v] )Low[u] = Low[v];        } else if(InStack[v] && Low[u] > DFN[v])            Low[u] = DFN[v];    }    if(Low[u] == DFN[u]) {        scc++;        do {            v = Stack[--top];            InStack[v] = false;            Belong[v] = scc;            num[scc]++;        } while( v != u);    }}LL fastpow(LL a, LL c) {    LL res = 1;    while (c) {        if (c & 1)            res = (res * a) % MOD;        a = (a * a) % MOD;        c >>= 1;    }    return res;}int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%d", &n)) {        edge_init();        Tarjan_init();        for (int i = 1; i <= n; i++) {            int t;            scanf("%d", &t);            edge_add(i, t);        }        for (int i = 1; i <= n; i++)            if (!DFN[i])                Tarjan(i);        LL ans = 1;        int tmp = n;        for (int i = 1; i <= scc; i++) {            if (num[i] > 1) {                ans = (ans * (fastpow(2, num[i]) - 2)) % MOD;                tmp -= num[i];            }        }        if (tmp)            ans = (ans * fastpow(2, tmp)) % MOD;        printf("%I64d\n", ans);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}


E. ZS and The Birthday Paradox

简单数学题。

一年2^n天,求k个人中有人生日是同一天的概率(1<=n,k<=1e18)。

假如一年365天,n个人中有人生日相同的概率为


所以这一题就是让求


然后求出分子分母的gcd约分就可以了。gcd一定是2^x的形式,因为分母已经是2^x的形式,所以只需要求出分子的因子2的个数。

对于1*2*3*...*k,因子2的个数为k/2+k/4+k/8...。

然后求出gcd的逆元,分子分母同时乘上逆元就得到结果了。

#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 2e5 + 50;const int MAXM = 2e5 + 50;LL n, k;LL fastpow(LL a, LL c) {    LL res = 1;    while (c) {        if (c & 1)            res = (res * a) % MOD;        a = (a * a) % MOD;        c >>= 1;    }    return res;}int main() {#ifdef LOCAL_NORTH    FIN;#endif // LOCAL_NORTH    while (~scanf("%I64d%I64d", &n, &k)) {        if (n <= 62 && k > (1LL << n)) {            printf("1 1\n");            continue;        }        LL cnt = 0;        LL p = fastpow(2, n);        for (LL i = k - 1; i >= 1; i >>= 1) {            cnt += i / 2;        }//        for (LL i = tmp - 1; i >= tmp - k + 1; i--) {//            LL ttmp = i & (-i);//            cnt += (LL)log2(ttmp);//        }        LL inv = fastpow(fastpow(2, cnt), MOD - 2);        LL up = 1, down = fastpow(p, k - 1);        for (LL i = 1; i <= k - 1; i++) {            LL tmp = (p - i + MOD) % MOD;            up = (up * tmp) % MOD;            if (tmp <= 0) //!!!                break;        }        up = up * inv % MOD;        down = down * inv % MOD;        up = (down - up + MOD) % MOD;        printf("%I64d %I64d\n", up, down);    }#ifdef LOCAL_NORTH    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH    return 0;}


1 0
原创粉丝点击