The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest E. Interesting Trip 长链剖分

题库链接

考虑莫比乌斯, 套上去之后就是变成了统计长度为d的一共有多少路径, 直接长链剖分,

在计蒜客上极度卡常, 卡了一万年才卡过去, 现场好像还有用点分治过去的, 这都能过??

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int N = (int)5e5 + 7;
const int M = 30000;

int n, d, a[N], vis[N], miu[M + 1];
int now_val, now_op, now_cnt, now_col;
int len[N], son[N], dp[N], *id, *f[N];
bool ok[N];
LL ans;

vector<int> V[M + 1];
vector<int> P[M + 1];

int edge_tot, head[N];
struct Edge {
    int to, nex;
} e[N << 1];

inline void addEdge(int u, int v) {
    e[edge_tot].to = v;
    e[edge_tot].nex = head[u];
    head[u] = edge_tot++;
}

bool checkNum(int x) {
    for(int i = 2; i * i <= x; i++) {
        if(x % (i * i) == 0) return false;
    }
    return true;
}

void prepare() {
    ok[1] = true;
    for(int i = 2; i <= M; i++) {
        if(checkNum(i)) ok[i] = true;
    }
    for(int i = 1; i <= M; i++) {
        for(int j = 1; j * j <= i; j++) {
            if(i % j) continue;
            if(ok[j]) V[i].push_back(j);
            if(j * j != i && ok[i / j]) V[i].push_back(i / j);
        }
    }
    miu[1] = 1;
    for(int i = 1; i <= M; i++) {
        for(int j = i + i; j <= M; j += i) {
            miu[j] -= miu[i];
        }
    }
}

void gao(int u, int fa) {
    now_cnt++;
    vis[u] = now_col;
    son[u] = len[u] = 0;
    for(int j = head[u], v; ~j; j = e[j].nex) {
        v = e[j].to;
        if(v == fa || a[v] % now_val) continue;
        gao(v, u);
        if(len[v] > len[u]) {
            len[u] = len[v];
            son[u] = v;
        }
    }
    len[u]++;
}

void dfs(int u, int fa) {
    f[u][0] = 1;
    if(son[u]) {
        f[son[u]] = f[u] + 1;
        dfs(son[u], u);
    }
    if(d < len[u]) {
        ans += now_op * f[u][d];
    }
    for(int j = head[u], v; ~j; j = e[j].nex) {
        v = e[j].to;
        if(v == fa || v == son[u] || a[v] % now_val) continue;
        f[v] = id; id += len[v];
        dfs(v, u);
        for(int i = 1; i <= len[v] && i <= d; i++) {
            if(d - i < len[u]) ans += 1LL * now_op * f[v][i - 1] * f[u][d - i];
        }
        for(int i = 1; i <= len[v] && i <= d; i++) {
            f[u][i] += f[v][i - 1];
        }
    }
}

void init() {
    ans = edge_tot = 0;
    for(int i = 1; i <= M; i++) {
        P[i].clear();
    }
    for(int i = 1; i <= n; i++) {
        head[i] = -1;
        vis[i] = 0;
    }
}

int main() {
    prepare();
    int cas = 0;
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &d);
        init();
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            for(auto &t : V[a[i]]) {
                P[t].push_back(i);
            }
        }
        for(int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        for(int i = 2; i <= M; i++) {
            if(!P[i].size()) continue;
            now_val = i; now_op = -miu[i]; now_col = i;
            for(auto &Rt : P[i]) {
                if(vis[Rt] == i) continue;
                now_cnt = 0;
                gao(Rt, 0);
                for(int i = 0; i <= now_cnt; i++) dp[i] = 0;
                id = dp;
                f[Rt] = id; id += len[Rt];
                dfs(Rt, 0);
            }
        }
        printf("Case #%d: %lld\n", ++cas, 2 * ans);
    }
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/11635002.html

时间: 2024-10-09 21:50:05

The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest E. Interesting Trip 长链剖分的相关文章

The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest C. Xyjj’s sequence(动态规划+欧拉降幂)

题目链接:https://nanti.jisuanke.com/t/40255 中文题面: 解题思路:先用欧拉降幂求出A,B两个序列,定义dp[0][i][j]为取A的前i个元素,B的前j个元素,且C的最后一个元素为B[j],同理dp[1][i][j]为取A的前i个元素,B的前j个元素,且C的最后一个元素为A[i],那么就很容易得到状态转移方程.那么最后答案即为max(dp[0][n][n],dp[1][n][n]).还有值得注意的是:该题需要使用滚动数组,不然会超内存. 在此贴两个关于欧拉降幂

The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest - F.Sequence(打表+线段树)

题意:给你一个长度为$n$的数组,定义函数$f(l,r)=a_{l} \oplus a_{l+1} \oplus...\oplus a_{r}$,$F(l,r)=f(l,l)\oplus f(l,l+1)\oplus ...\oplus f(l,r)\oplus f(l+1,l+1)\oplus ...f(l+1,r)\oplus ...\oplus f(r,r)$,有两种操作,第一种将数组中某个元素$a[x]$变为$y$,第二种计算$F(l,r)$的值. 思路:打表后发现只有当$l$和$r$同

The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest

打网络赛 比赛前的准备工作要做好 确保 c++/java/python的编译器能用 打好模板,放在桌面 A. PERFECT NUMBER PROBLEM 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <se

The Preliminary Contest for ICPC China Nanchang National Invitational I题

Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval. Now she is planning to find the max value of the intervals in her array. Can you h

The Preliminary Contest for ICPC China Nanchang National Invitational I.Max answer单调栈

题面 题意:一个5e5的数组,定义一个区间的值为 这个区间的和*这个区间的最小值,注意数组值有负数有正数,求所有区间中最大的值 题解:如果全是正数,那就是原题 POJ2796 单调栈做一下就ok 我们现在有负数,考虑这段区间,他的和必须是负数,由于导致和为负数,最小值一定也是负数, 那对于这样一个和为负的区间进行扩展的时候,遇见下一个数,是负数,我们一定会扩展,无论这个负数大小 遇见下一个是正数,如果和没有变正,那就可以继续扩展下去(不更新答案罢了) 所以我们对于那些和为负的区间,单独统计一下答

2019 ICPC Malaysia National G(拓扑排序)

2019 ICPC Malaysia National G 有点绕,两层拓扑排序. 有空再补详细. 甚至有点丑,因为绕,为了区分,当时变量名写得很长. #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<vector> #define debug printf("!") using namespace std; type

2019 ICPC Malaysia National F(状态压缩)

2019 ICPC Malaysia National F 赛后补题.看了这个题解,说是状态压缩. 以第一行的士兵为主,第二行士兵为次,即,第二行被第一行士兵匹配,更新第一行士兵的状态. 用当前第i个士兵的状态更新第i+1个士兵的状态. f[i][j]:i为士兵的下标,j为第i个士兵的状态.(1<j<(1<<(e*2+1))). 比如e=3,二进制 j=1000011,表示第i个士兵之前包括第i个士兵,在[i-3,i+3]范围内,第二行的士兵已被匹配了下标为i-3,i+2,i+3的

2019 ICPC 南昌网络赛

2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 // 史上排名最高一次,开场不到两小时队友各A一题加水题共四题,排名瞬间升至三四十名 // 然后后三小时就自闭了,一题都没有突破...最后排名211 hhhh ? ? B. Fire-Fighting Hero 题意 队友做的,待补. ? AC代码 #include<cstdio> #includ

The 2018 ACM-ICPC China JiangSu Provincial Programming Contest快速幂取模及求逆元

题目来源 The 2018 ACM-ICPC China JiangSu Provincial Programming Contest 35.4% 1000ms 65536K Persona5 Persona5 is a famous video game. In the game, you are going to build relationship with your friends. You have N friends and each friends have his upper b