map实现的dp求助
查看原帖
map实现的dp求助
618344
powehi1楼主2024/8/24 23:19

dp[u][d]表示以u为根的子树,包含u这个节点且公因数为d的最大链长(不横跨两个子树,这里的链指的是u节点和它的一个子树的部分点形成的链)。不过答案链长可能会横跨u的两个子树,这个在转移的时候考虑到了。

在cf上wa on 6,比答案多1。代码里面有部分注释

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

#define endl '\n' 
#define int long long
const int N = 1e6+5, mod = 1e9+7;

int a[N];
vector<int> g[N];
map<int,int> dp[N];

void solve(){

    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<n;i++) {
        int a, b;
        cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    int ans = 0;
    auto dfs = [&](auto dfs, int u, int fa) ->void {
        dp[u][a[u]] = 1;
        if(a[u]!=1) ans = max(ans,1ll);
        for(int v : g[u]) {
            if(v==fa) continue;
            dfs(dfs,v,u);
            for(auto [x,y] : dp[v]) {
                int d = __gcd(x,a[u]);
                if(dp[u].count(d)) {
                    if(d!=1) ans = max(ans,dp[u][d]+y); // 横跨u的两个子树形成的链
                    dp[u][d] = max(dp[u][d],y+1); // 更新最大链长,不横跨子树,只含u和它的一个子树
                }
                else {
                    dp[u][d] = y+1;
                }
                if(d!=1) ans = max(ans,dp[u][d]); 
            }
        }
    };

    dfs(dfs,1,0);

    cout<<ans<<endl;

} 

signed main() {

    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    // int T;
    // cin>>T;
    // while(T--)
    solve();
}

2024/8/24 23:19
加载中...