CF1778F Maximizing Root 【贪心】【数学】

容易想到,选的点应该是和\(1\)连通的连通块。最后的答案是\(a[1]\)乘以\(a[1]\)的因子。

所以我们枚举\(a[1]\)的因子,然后判断是否能让所有点都变成\(a[1]\)的因子的倍数。我们容易发现,其实对于每个点而言,一次选中操作都相当于把它的幂次翻倍。

于是我们可以预处理出\(u\)变成\(v\)的倍数需要翻几倍,然后做树上前缀和,就可以求出要变化多少个点了。

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

const int maxn = 205000;

int n,k;
int a[maxn],b[maxn];
vector<int> g[maxn],res[maxn];

vector <int> factor[1030];
int ok[maxn],dep[maxn];
int sta[maxn];
int gd[1030][1030];

void dfs(int now,int pa,int dp){
    dep[now] = dp;
    for(auto x:g[now]){
	if(x == pa) continue;
	dfs(x,now,dp+1);
    }
}

void dfs2(int now,int pa){
    sta[dep[now]] = now;
    for(auto x:g[now]){
	if(x == pa) continue;
	dfs2(x,now);
    }
    for(auto z:res[now]){
	ok[sta[z]] = 1;
    }
    sta[dep[now]] = 0;
}

void dfs3(int now,int pa){
    for(auto x:g[now]){
	if(x == pa) continue;
	dfs3(x,now);
	ok[now] |= ok[x];
    }
}

int check(int mul){
    for(int i=1;i<=n;i++) {ok[i] = 0;res[i].clear();}
    for(int i=1;i<=n;i++) b[i] = __gcd(a[i],mul);
    for(int i=1;i<=n;i++){
	if(gd[b[i]][mul] == 0) return false;
	int tms = gd[b[i]][mul];
	/*while(dt != mul){
	    tms++;
	    dt = dt*dt;
	    dt = __gcd(dt,mul);
	    }*/
	//paint(i,tms);
	if(tms > dep[i]) return false;
	res[i].push_back(tms);
    }
    dfs2(1,0);
    dfs3(1,0);
    int cnt = 0;
    for(int i=1;i<=n;i++){
	if(ok[i]) cnt ++;
    }
    if(cnt > k) return false;
    else return true;
}

int dpi(int u,int v){
    if(u == v) return 1;
    if(gd[u][v]) return gd[u][v];
    else{
	u = u*u;
	u = __gcd(u,v);
	return dpi(u,v)+1;
    }
}

int pri[1050],flag[1050];

int main(){
    for(int i=2;i<=1000;i++){
	for(int j=1;j*i<=1000;j++) factor[i*j].push_back(i);
    }
    for(int i=2;i<=1000;i++){
	if(!flag[i]){
	    pri[i] = i;
	    for(int j=2;j*i<=1000;j++){
		if(!flag[i*j]) pri[i*j] = i;
		flag[i*j] = 1;
	    }
	}
    }
    for(int i=2;i<=1000;i++){
	for(int j=1;j*i<=1000;j++){
	    int pp = j,ys = 1;
	    while(pp != 1){
		int po = pri[pp];
		if(i%po) ys = 0;
		pp /= pri[pp];
	    }
	    if(ys) gd[i][i*j] = dpi(i,i*j);
	}
    }
    int t; cin >> t;
    while(t--){
	cin >> n >> k;
	for(int i=1;i<=n;i++) g[i].clear();
	for(int i=1;i<=n;i++) cin >> a[i];
	for(int i=1;i<n;i++){
	    int u,v; cin >> u >> v;
	    g[u].push_back(v);
	    g[v].push_back(u);
	}
	dfs(1,0,1);
	int ans = a[1];
	for(auto mul:factor[a[1]]){
	    if(check(mul)) ans = max(ans,a[1]*mul);
	}
	cout<<ans<<endl;
    }
    return 0;
}
posted @ 2023-02-02 18:06  menhera  阅读(53)  评论(0编辑  收藏  举报