2020 Multi-University Training Contest 3

Tokitsukaze, CSL and Palindrome Game
Lady Layton and Stone Game
Tokitsukaze and Colorful Tree

Tokitsukaze and Multiple

1 0 5 10^5 105 的区间,显然不能用两个for把所有的区间和求出来,
将每个前缀和 % p \% p %p,如果前缀和 sum[i] = sum[ i前面某个位置 k]
说明 a[k]+a[k+1]+…+a[i] 是 p 的倍数,是可以合并的一个区间,
dp找答案最大值

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int a[N], sum[N], dp[N], pre[N];
int n, m, k;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int T;
    cin >> T;
    while (T--) {
        cin >> n >> m;

        memset(dp, 0, sizeof dp);
        memset(pre, 0, sizeof pre);

        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            a[i] %= m;
            sum[i] = ((ll) sum[i - 1] + a[i]) % m;

            dp[i] = dp[i - 1];
            if (pre[sum[i]] || (pre[sum[i]] == 0 && sum[i] == 0))
                dp[i] = max(dp[i], dp[pre[sum[i]]] + 1);

            pre[sum[i]] = i;
        }
        cout << dp[n] << endl;
    }

    return 0;
}

Little W and Contest

官方题解
在这里插入图片描述
( 1 + n x 1 y 1 + m x 1 y 2 ) (1+nx^1y^1+mx^1y^2) (1+nx1y1+mx1y2)

要么选n个人中的一个,要么选m个人中的一个,要么谁都不选
其中1表示这个连通块什么人都不选

母函数 = ( 1 + x 1 ) ( 1 + x 2 ) . . . ( 1 + x n ) = 1 + k 1 x 1 + k 2 x 2 . . . + k n x n =(1+x^1)(1+x^2)...(1+x^n)=1+k_1x^1+k_2x^2...+k_nx^n =(1+x1)(1+x2)...(1+xn)=1+k1x1+k2x2...+knxn

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int n;
// 借助x表示人数 借助y表示战斗力
// kx^ay^b 表示 a人组成战斗力为b的团队 方案总数为k
// 对于一个有n人战斗力为1  m人战斗力为2的连通块 则可以用多项式 (nxy + mxy2 + 1) 来表示

//母函数 生成函数
// 能使用的前提 幂小
struct GeneratingFunction {
    ll k[4][7];// k[a][b] 最多3个人 战斗力不超过6 
    GeneratingFunction() {
        memset(k, 0, sizeof k);
        k[0][0] = 1;
    }

    void init() {
        memset(k, 0, sizeof k);
        k[0][0] = 1;
    }

    // 母函数乘法  正贡献01背包
    void mult(ll n, ll m) {
        for (int i = 3; i; i--) {
            for (int j = 6; j; j--) {
                k[i][j] += n * k[i - 1][j - 1] % mod;// nx^1y^1
                if (j > 1)
                    k[i][j] += m * k[i - 1][j - 2] % mod; // mx^1y^2
                k[i][j] %= mod;
            }
        }
    }

    //母函数除法 负贡献完全背包
    void div(ll n, ll m) {
        for (int i = 1; i <= 3; i++) {
            for (int j = 1; j <= 6; j++) {
                k[i][j] -= n * k[i - 1][j - 1] % mod;// nx^1y^1
                if (j > 1)
                    k[i][j] -= m * k[i - 1][j - 2] % mod; // mx^1y^2
                k[i][j] = (k[i][j] % mod + mod) % mod;
            }
        }
    }

    ll get() {
        return (k[3][5] + k[3][6]) % mod;
    }
} GF;


int a[N], b[N];

int fa[N];

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

void Union(int x, int y) {
    int fx = find(x);
    int fy = find(y);
    if (fx == fy) return;
    if (fx < fy) {
        fa[fy] = fx;
        a[fx] += a[fy];
        b[fx] += b[fy];
    } else {
        fa[fx] = fy;
        a[fy] += a[fx];
        b[fy] += b[fx];
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T;
    cin >> T;
    for (int cs = 1; cs <= T; cs++) {

        cin >> n;
        GF.init();
        
        for (int i = 1, x; i <= n; i++) {
            cin >> x;
            fa[i] = i;
            a[i] = b[i] = 0;
            if (x == 1) a[i]++;
            else b[i]++;
            
            GF.mult(a[i], b[i]);
        }

        cout << GF.get() << endl;
        for (int i = 1, u, v; i < n; i++) {
            cin >> u >> v;
            GF.div(a[find(u)], b[find(u)]);
            GF.div(a[find(v)], b[find(v)]);
            Union(u, v);
            GF.mult(a[find(u)], b[find(v)]);
            cout << GF.get() << endl;
        }

    }
    return 0;
}

X Number

Tokitsukaze and Rescue

完全图上有预谋的删除k条路径,问最后最长的最短路, k ≤ 5 k\le5 k5 n ≤ 50 n\le50 n50
要删除的边一定在最短路上

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e2 + 10;
int e[N][N];
int ans = 0;
int n, m, k;

int dis[N], vis[N];
int pre[N];

int del[N][N];//del[i][j]表示点i->点j这条边被删除

void dijkstra() {
    memset(pre, 0, sizeof pre);
    memset(dis, INF, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[1] = 0;
    pre[1] = 0;
    for (int i = 1; i < n; i++) {
        int d = INF, f = 0;
        //找到当前能够找到的最短路
        for (int j = 1; j <= n; j++) {
            if (!vis[j] && dis[j] < d) {
                d = dis[j], f = j;
            }
        }
        vis[f] = 1;
        for (int j = 1; j <= n; j++) {
            if (dis[j] > dis[f] + e[f][j] && !del[f][j]) {
                dis[j] = dis[f] + e[f][j];
                pre[j] = f;
            }
        }
    }
}

void dfs(int x) {
    //每次都先找出一条最短路
    dijkstra();
    if (x == k + 1) {
        ans = max(ans, dis[n]);
        return;
    }

    // 沿着最短路 依次枚举删除的是哪一条边 直到删了k条
    for (int i = n, j = pre[i]; i; i = j, j = pre[i]) {
        del[i][j] = del[j][i] = 1;
        dfs(x + 1);
        del[i][j] = del[j][i] = 0;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
 
    int T;
    cin >> T;
    for (int cs = 1; cs <= T; cs++) {

        cin >> n >> k;
        for (int i = 1, u, v, w, lim = n * (n - 1) / 2; i <= lim; i++) {
            cin >> u >> v >> w;
            e[u][v] = e[v][u] = w;
        }

        ans = 0;
        dfs(1);
        cout << ans << endl;
    }
    return 0;
}

Triangle Collision


Parentheses Matching
Play osu! on Your Tablet
Game on a Circle

©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页