HDU 6643 Ridiculous Netizens (点分治+ dp + 整除分块)

传送门

代码

/*************************************************************************
	> File Name: 1.cpp
	> Author: Knowledge_llz
	> Mail: 925538513@qq.com 
	> Blog: https://www.cnblogs.com/Knowledge-Pig/ 
	> Created Time: 2021/11/15 11:35:21
 ************************************************************************/

#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define LL long long
#define pb push_back
#define fi first
#define se second
#define pr pair<int,int>
#define mk(a,b) make_pair(a,b)
#define endl '\n'
using namespace std;
const int mod = 1e9 + 7;
int n, m, tot, a[2021], cnt, rt, w[2021], f[1000005], sz[2021], max_son[2021], ans = 0;
int dp[2021][2021];
vector<int> vec[2021];
bool vis[2021];
void add(int &x, int y){ x = (x + y) % mod; }
void find_rt(int id, int fa){
	sz[id] = 1; max_son[id] = 0;
	for(auto u : vec[id]){
		if(vis[u] || u == fa) continue;
		find_rt(u, id);
		sz[id] += sz[u];
		max_son[id] = max(max_son[id], sz[u]);
	}
	max_son[id] = max(max_son[id], tot - sz[id]);
	if(max_son[id] < max_son[rt]) rt = id;
}
void dfs(int id, int fa){
	sz[id] = 1;
	for(int i = 0; i <= cnt; ++i) dp[id][i] = 0;
	for(int i = 1; i <= cnt; ++i) add(dp[id][f[w[i] / a[id]]], dp[fa][i]);
	for(auto u : vec[id]){
		if(vis[u] || u == fa) continue;
		dfs(u, id);
		for(int i = 1;  i <= cnt; ++i) add(dp[id][i], dp[u][i]);
		sz[id] += sz[u];
	}
}
void solve(int id){
	rt = 0; find_rt(id, 0);
	dp[0][1] = 1;
	dfs(rt, 0); vis[rt] = 1;
	for(int j = 1; j <= cnt; ++j) add(ans, dp[rt][j]);
	int g = rt;
	for(auto u : vec[g])
		if(!vis[u]){
			tot = sz[u];
			solve(u);
		}
}
int main(){
	ios::sync_with_stdio(false); cin.tie(0);
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
#endif
	int T; cin >> T; max_son[0] = 1e9; 
	while(T--){
		cin >> n >> m;  cnt = ans = 0;
		for(int i = 1; i <= n; ++i){ 
			cin >> a[i];
			vec[i].clear(); 
			vis[i] = 0;
		} 
		for(int i = 1, pre = 0; i <= m; ++i){
			int x = m / i;
			if(x != pre) w[++cnt] = x, pre = x, f[x] = cnt;
		}
		for(int i = 1, u, v; i < n; ++i){
			cin >> u >> v;
			vec[u].pb(v);  vec[v].pb(u);
		}
		tot = n; solve(1);
		cout << ans << endl;
	}
	return 0;
}
posted @ 2021-11-16 19:10  Knowledge-Pig  阅读(36)  评论(0编辑  收藏  举报