Codeforces Round #369 (Div. 2)解题报告

原创 2016年08月30日 20:29:39

A. Bus to Udayland
1、题意:找个OO改成++。题面
2、分析:mdzz…..

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000010

inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

char ch[1010][10];

int main(){
    int n = read();
    for(int i = 1; i <= n; i ++) scanf("%s", ch[i]);
    for(int i = 1; i <= n; i ++){
        if(ch[i][0] == 'O' && ch[i][1] == 'O'){
            puts("YES");
            for(int j = 1; j <= n; j ++){
                if(j != i) printf("%s\n", ch[j]);
                else printf("++%c%c%c\n", ch[j][2], ch[j][3], ch[j][4]);
            }
            return 0;
        }
        if(ch[i][3] == 'O' && ch[i][4] == 'O'){
            puts("YES");
            for(int j = 1; j <= n; j ++){
                if(j != i) printf("%s\n", ch[j]);
                else printf("%c%c%c++\n", ch[j][0], ch[j][1], ch[j][2]);
            }
            return 0;
        }
    }
    puts("NO");
    return 0;
}

B. Chris and Magic Square 题面
1、题意:在一个矩阵中让你填一个数,填完之后满足所有的行,所有的列以及两条对角线的和相等。
2、分析:我们首先随便找一个没有这个数的行,算出sum,然后此位置的一行相减,求出这个数,然后判断一下和是否相等就行。注意n=1

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 510
#define LL long long

inline LL read(){
    char ch = getchar(); LL x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

LL a[M][M];

int main(){
    LL n = read(); LL x, y;
    for(LL i = 1; i <= n; i ++){
        for(LL j = 1; j <= n; j ++){
            a[i][j] = read();
            if(a[i][j] == 0) x = i, y = j;
        }
    } 
    if(n == 1){
        puts("1");
        return 0;
    }
    LL t = 1;
    if(x == t){
        t ++;
    }
    LL sum = 0, tsum = 0;
    for(LL i = 1; i <= n; i ++) sum += a[t][i];
    for(LL i = 1; i <= n; i ++) if(i != y) tsum += a[x][i];
    LL ans = sum - tsum; tsum = sum;
    a[x][y] = ans;
    for(LL i = 1; i <= n; i ++){
        sum = 0;
        for(LL j = 1; j <= n; j ++) sum += a[i][j];
        if(sum != tsum){
            return puts("-1"), 0;
        }
    }
    for(LL i = 1; i <= n; i ++){
        sum = 0;
        for(LL j = 1; j <= n; j ++) sum += a[j][i];
        if(sum != tsum){
            return puts("-1"), 0;
        }
    }
    sum = 0;
    for(LL i = 1; i <= n; i ++){
        sum += a[i][i];
    }
    if(sum != tsum) return puts("-1"), 0;
    sum = 0;
    for(LL i = 1; i <= n; i ++){
        sum += a[n - i + 1][i];
    }
    if(sum != tsum) return puts("-1"), 0;
    if(ans < 1) return puts("-1"), 0; 
    printf("%I64d\n", ans);
    return 0;
}

C. Coloring Trees 题面
1、题意:给一排树,有些树有颜色,有些没有,你需要给没有颜色的树染上颜色,第i棵树染成j颜色需要用pi,j块钱,将这一排数染成w段颜色需要最少用多少块钱。
2、分析:一眼题,随手写一发dp咯,f[i][j][k]表示第i棵树、这个树是j颜色,已经有k段了,转移随便yy一下就好了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 110
#define LL long long

inline int read(){
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

LL f[M][M][M];
int col[M];
LL p[M][M];

int main(){
    int n = read(), m = read(), k = read();
    for(int i = 1; i <= n; i ++) col[i] = read();
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= m; j ++){
            scanf("%I64d", &p[i][j]);
        }
    }
    memset(f, 0x3f, sizeof(f));
    f[0][0][0] = 0;
    for(int i = 0; i < n; i ++){
        for(int j = 0; j <= k; j ++){
            for(int k = 0; k <= m; k ++){
                if(f[i][j][k] == 0x3f3f3f3f3f3f3f3fll) continue;
                if(col[i + 1]){
                    f[i + 1][j + (k != col[i + 1])][col[i + 1]] = min(f[i][j][k], f[i + 1][j + (k != col[i + 1])][col[i + 1]]);
                }
                else{
                    for(int w = 1; w <= m; w ++){
                        f[i + 1][j + (k != w)][w] = min(f[i][j][k] + p[i + 1][w], f[i + 1][j + (k != w)][w]);
                    }
                }
            }
        }
    }
    LL ans = 0x3f3f3f3f3f3f3f3fll;
    for(int i = 0; i <= m; i ++) ans = min(ans, f[n][k][i]);
    if(ans == 0x3f3f3f3f3f3f3f3fll) ans = -1;
    printf("%I64d\n", ans);
    return 0;
}

D. Directed Roads 题面
1、题意:n个点n条边的有向图,你可以改变有向边的方向,问改成没有环的方案数。
2、分析:一眼题。。很显然,每一个联通分量里面只会有一个简单环= =|||,在每个联通分量里面,这个简单环不能变成环的方案数明显是2size2,环外的边就无所谓咯。拿个并查集维护一下就好了,最后所有联通分量的乘积就是答案。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 400010
#define LL long long
#define MOD 1000000007ll

inline LL read(){
    char ch = getchar(); LL x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

struct Node{
    LL x, y;
} a[M];

struct Edge{
    LL u, v, next;
} G[M];
LL head[M], tot;

LL fa[M], sz[M], fk[M];

inline LL find(LL x){
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

LL res;

inline void dfs(LL x, LL t, LL y, LL ff){
    if(x == y){
        res = t;
        return;
    }
    for(LL i = head[x]; i != -1; i = G[i].next) if(G[i].v != ff){
        dfs(G[i].v, t + 1, y, x);
        if(res) return; 
    }
}

inline void add(LL x, LL y){
    G[++ tot] = (Edge){x, y, head[x]};
    head[x] = tot;
    G[++ tot] = (Edge){y, x, head[y]};
    head[y] = tot;
}

LL pow[M];

int main(){
    memset(head, -1, sizeof(head));
    LL n = read();
    for(LL i = 1; i <= n; i ++){
        LL x = read();
        a[i] = (Node){i, x};
    }
    pow[0] = 1;
    for(LL i = 1; i <= n; i ++) pow[i] = pow[i - 1] * 2 % MOD; 
    for(LL i = 1; i <= n; i ++) fa[i] = i, sz[i] = 1;
    LL ans = 1;
    for(LL i = 1; i <= n; i ++){
        LL x = a[i].x, y = a[i].y;
        LL p = find(x), q = find(y);
        if(p == q){
            res = 0; 
            dfs(x, 1, y, 0);
            ans *= pow[sz[p] - res];
            ans %= MOD;
            ans *= (pow[res] + MOD - 2);
            ans %= MOD;
            fk[p] = 1;
        }
        else fa[p] = q, add(x, y), sz[q] += sz[p], fk[q] |= fk[p], ans = ans * (fk[p] ? pow[sz[q] - sz[p]] : (fk[q] ? pow[sz[p]] : 1ll)) % MOD;
    }
    printf("%I64d\n", ans);
    return 0;
}

E. ZS and The Birthday Paradox
1、题意:让你求2nk(2n+2n1+...+2nk+1)2nk
2、分析:额,你想问为啥是求那个式子么,自行百度生日悖论,然后就是这个式子了。。这个式子怎么做,观察此题的特点,我们发现MOD非常小,才106+3,从MOD入手,当k≥MOD时,分子是0。。否则就暴力算出分子,分母还用说么。怎么约分呢?我们可以这样,观察分母,我们发现分母只有一个质因子,那就是2!于是我们logk的时间算出分子中有多少个2就行了。。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000010
#define MOD 1000003
#define LL long long
#define ULL unsigned long long

inline LL read(){
    char ch = getchar(); LL x = 0, f = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

inline LL pow(LL x, LL y){
    while(y < 0) y += MOD;
    LL ret = 1;
    while(y){
        if(y & 1) (ret *= x) %= MOD;
        (x *= x) %= MOD;
        y >>= 1;
    }
    return ret;
}

int main(){
    LL n, k;
    n = read(), k = read();
    if(n < 63){
        if(k > (1ll << n)){
            return puts("1 1"), 0;
        }
    }
    LL up, down;
    if(k >= MOD) up = 0;
    else{
        up = 1;
        for(LL i = 1; i < k; i ++){
            up = (up * (pow(2ll, n) - i)) % MOD;
        }
    }
    //printf("%lld\n", up);
    down = pow(pow(2ll, n), k - 1);
    for(ULL i = 2; i < k; i <<= 1){
        LL t = pow(pow(2ll, (k - 1) / i), MOD - 2);
        up = (up * t) % MOD;
        down = (down * t) % MOD;
    }
    up = (down - up + MOD) % MOD;
    printf("%I64d %I64d\n", up, down); 
    return 0;
}

总结:这次的比赛,赛场上只做出来4道题,另外代码的准确度不够,前四道题完全可以在50分钟内完成,这样能为最后一道题节约出时间。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

codeforces Round #264(div2) B解题报告

B. Caisa and Pylons time limit per test 1 second memory limit per test 256 megabytes ...

Codeforces Round #401 (div. 2)解题报告

Problem A-Shell Game 找规律 6个一组 //Author: Lixiang #include struct Shell_Game{ int N,X; void init()...

codeforces Round #238(div2) B解题报告

B. Domino Effect time limit per test 1 second memory limit per test 256 megabytes i...

codeforces round 200 div2解题报告

A. Magnets time limit per test 1 second memory limit per test 256 megabytes input ...

Codeforces Round #273 (Div. 2) 解题报告 (A B C D)

A. Initial Bet

codeforces Round #261(div2) A解题报告

A. Pashmak and Garden time limit per test 1 second memory limit per test 256 megabytes ...

【解题报告】Codeforces Round #344 (Div. 2)

简略的解题报告。

Codeforces Round #241 (Div. 2) 解题报告

Codeforces Round #241 (Div. 2) A. Guess a number! time limit per test 1 secon...
  • kbdwo
  • kbdwo
  • 2014-04-17 14:07
  • 721

【解题报告】Codeforces Round #401 (Div. 2)

简略的解题报告。

Codeforces Round #291 (Div. 2) 解题报告 (A B C D)

A Chewbaсca and Number         贪心,每一位取t和9-t中较小的。注意首位不能为0。 #include #include #include #incl...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)