网易笔试:求所有子树因子个数

题目具体不记得了,事后写的题解,感兴趣可以交流
主要是用到唯一分解定理和回溯算法,处理出每个节点的质因子列表,向上合并

// 测试样例
	

5

1 2

1 3

2 4

2 5

1 2 3 4 5


#include <iostream>
#include <unordered_set>
#include <unordered_map>
using namespace std;
typedef long long  ll;
unordered_map<int, unordered_set<int> > G; //树
const int maxn = 5e4+5;
const ll mod = 1e9+7;
ll ans[maxn]; //答案
unordered_map<int, int> value; // 节点i的值
unordered_map<int, unordered_map<int, int>* > factors; //每个节点所代表的子树的乘积的质因子列表

unordered_map<int, int>* dfs(int u){
    unordered_map<int, int>* mp = new unordered_map<int, int>();
    int cur = value[u];
    // 计算当前节点u的质因子
    while(cur > 1){
        for(int i=2; i<=cur; i++){ //可以用质数打表优化一下
            if( (cur % i) == 0){
                (*mp)[i]++;
                cur /= i;
            }
        }
    }
    for(auto x : G[u]){
        auto ret = factors[x] ? factors[x] : dfs(x); //记忆化搜索
        for(auto x : *ret){ //合并到根节点
            (*mp)[x.first] += x.second;
        }
    }
    ll num = 1;
//    打印每个节点的质因子情况 质因子 : 数量
//    cout<<"u = "<<u<<endl;
//    for(auto x : *mp){
//        cout<<x.first<<" : "<<x.second<<endl;
//    }
    for(auto x : *mp){
        num *= (x.second+1);
        num %= mod;
    }
    ans[u] = num;
    return factors[u] = mp;
}
int main(){
    int n,u,v,x;
    cin>>n;
    for(int i=1; i<=n-1; i++){
        cin>>u>>v;
        G[u].insert(v);
    }
    for(int i=1; i<=n; i++) {
        cin>>x;
        value[i] = x;
    }
    dfs(1);
    for(int i=1; i<=n; i++) delete factors[i];
    for(int i=1; i<=n; i++) cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}




全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务