// 比赛过去很久了,由于马上要打区域赛,整理一下当时的题解
比赛时间:2019.9.24
题目来源:https://codeforces.com/gym/101412


 

A Ginkgo Numbers

水题,根据第一条提示暴力判断即可。

 

C One-Dimensional Cellular Automaton

在队友提示下,每一行可以由前一行矩阵递推得到,矩阵快速幂

#include<cstdio>
using namespace std;
int N, M;
int arr[52];
struct Mat {
    int m[52][52];
    Mat operator*(const Mat& a) {
        Mat res = {0};
        for(int i=1;i<=N;i++) {
            for(int j=1;j<=N;j++) {
                for(int k=1;k<=N;k++) {
                    if(m[i][k] && a.m[k][j])
                        res.m[i][j] = (res.m[i][j]+ m[i][k]*a.m[k][j]) % M;
                }
            }
        }
        return res;
    }
};

Mat getI() {
    Mat I = {0};
    for(int i=1;i<=50;i++) {
        I.m[i][i] = 1;
    }
    return I;
}

const Mat I = getI();

void qpow(Mat a, int n) {
    Mat res = I;
    while(n) {
        if(n&1) res = res*a;
        a = a*a;
        n >>= 1;
    }

    for(int i=1;i<=N;i++) {
        int ans = 0;
        for(int j=1;j<=N;j++) {
            ans = (ans + res.m[i][j]*arr[j]) % M;
        }
        printf("%d%c", ans, i==N?'\n':' ');
    }
}

int main() {
    int A, B, C, T;
    while(scanf("%d %d %d %d %d %d", &N, &M, &A, &B, &C, &T)!=EOF && N) {

        for(int i=1;i<=N;i++) {
            scanf("%d", &arr[i]);
        }

        Mat a = {0};
        a.m[1][1] = B, a.m[1][2] = C;
        a.m[N][N-1] = A, a.m[N][N] = B;
        for(int i=2;i<=N-1;i++) {
            a.m[i][i-1] = A;
            a.m[i][i] = B;
            a.m[i][i+1] = C;
        }
        qpow(a, T);
    }
    return 0;
}

 

D Find the Outlier

高斯消元
精度比较坑。。。

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;

double a[8][8], x[8], xx[8];
const double eps = 1e-9;

// double a[MAXN][MAXN],x[MAXN];//方程的左边的矩阵和等式右边的值,求解之后x存的就是结果
int equ, var; //方程数和未知数个数
/*
*返回0表示无解,1表示有解
*/
int Gauss() {
    int k, col, max_r;
    for(k=0,col=0;k<equ&&col<var;k++,col++) {
        max_r = k;
        for(int i=k+1;i<equ;i++) {
            if(fabs(a[i][col])>fabs(a[max_r][col]))
                max_r = i;
        }
        if(fabs(a[max_r][col])<eps) return 0;

        if(k!=max_r) {
            for(int j=col;j<var;j++) {
                swap(a[k][j], a[max_r][j]);
            }
            swap(x[k], x[max_r]);
        }

        x[k] /= a[k][col];
        for(int j=col+1;j<var;j++) {
            a[k][j] /= a[k][col];
        }
        a[k][col] = 1;

        for(int i=0;i<equ;i++) {
            if(i==k) continue;

            x[i] -= x[k]*a[i][col];
            for(int j=col+1;j<var;j++)
                a[i][j] -= a[k][j]*a[i][col];
            a[i][col] = 0;
        }
    }
    return 1;
}

int main() {
    int d;
    while(scanf("%d", &d)!=EOF && d) {
        for(int i=0;i<d+3;i++) {
            scanf("%lf", &xx[i]);
        }

        var = d+1;
        equ = d+1;
        int ans;
        double err = 0.0;
        for(int k=0;k<d+3;k++) {
            int cnt = 0;
            for(int i=0;i<d+3;i++) {
                if(i==k) continue;
                if(cnt>=d+1) break;

                a[cnt][0] = 1;
                for(int j=1;j<d+1;j++) {
                    a[cnt][j] = a[cnt][j-1]*i;
                }
                x[cnt] = xx[i];
                ++cnt;
            }

            /*
            for(int i=0;i<cnt;i++) {
                for(int j=0;j<d+1;j++) {
                    printf("%.2lf ", a[i][j]);
                }
                printf("%.2lf\n", x[i]);
            }
            */

            if(Gauss()==0) continue;

            int pos;
            if(k!=d+2) {
                pos = d+2;
            } else {
                pos = d+1;
            }
            double check = 0.0;
            double p = 1.0;
            for(int i=0;i<d+1;i++) {
                check += p*x[i];
                p = p*pos;
            }
            // printf("%.2lf %.2lf\n", check, xx[pos]);
            if(fabs(check-xx[pos])>0.01) continue;

            check = 0.0, p = 1.0;
            for(int i=0;i<d+1;i++) {
                check += p*x[i];
                p = p*k;
            }
            if(fabs(check-xx[k])>err) {
                ans = k;
                err = fabs(check-xx[k]);
            }
        }
        printf("%d\n", ans);

    }
    return 0;
}

 

F Never Wait for Weights

给定n个人中两人体重的差值信息,询问任意两人体重的差。并查集维护差值。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 100100;
int fa[maxn];
int w[maxn];

int Find(int x) {
    if(x==fa[x]) return x;

    int root = Find(fa[x]);
    w[x] += w[fa[x]];
    return fa[x] = root;
}

int main() {
    int n, m;
    while(scanf("%d %d", &n, &m)!=EOF && n) {
        for(int i=0;i<=n;i++) {
            fa[i] = i;
            w[i] = 0;
        }

        int x, y, dif;
        while(m--) {
            char op[3];
            scanf("%s", op);
            if(op[0]=='!') {
                scanf("%d %d %d", &x, &y, &dif);
                int a = Find(x);
                int b = Find(y);

                if(a!=b) {
                    fa[b] = a;
                    w[b] = w[x] - w[y] + dif;
                }
            } else {
                scanf("%d %d", &x, &y);
                int a = Find(x);
                int b = Find(y);
                if(a==b)
                    printf("%d\n", w[y]-w[x]);
                else
                    printf("UNKNOWN\n");
            }
        }
    }
    return 0;
}
 
01-22 11:53