[HDU multi-school] Ridiculous Netizens
- Dotted rule
- Divided into two portions: a certain point P, through the communication block P with or without P.
- After dependency tree using backpack P
- Without partial recursive calculation of P
- Tree dependent backpack
- v points must be transferred from point u by his father
- I.e., it must pass through the point P
- \(dp[v][s*a[v]]+=dp[u][s]\)
- The second dimension representing the product of the communication block
- The first dimension representing the number of the program passes through the point P and a certain point
- So in the end the parent node plus the number of sub-node solution
- Space Optimization
- The second dimension is not that big
- Slightly change the meaning, but also into a "hold" how much volume
- \ (\ lfloor \ frac {m } {s} \ rfloor \) can be divided into a number of equivalent state
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2010;
const int mod = 1e9+7;
struct edge{
int to,next;
}e[maxn<<1];
ll val[maxn],kuai[maxn];
ll dp[maxn][maxn];
int nowN,rt,maxP,head[maxn],tol,cnt,n;
int Size[maxn];
bool vis[maxn<<1];
ll ans;
int m;
inline void Mod(ll &a,ll b){
a=a+b<mod?a+b:a+b-mod;
}
void init(int n){
tol=1;
for(int i=0;i<=n;++i){
head[i]=0;
}
rt=0;
cnt=ans=0;
}
void add(int u,int v){
tol++;
vis[tol]=0;
e[tol].to=v;
e[tol].next=head[u];
head[u]=tol;
}
void get_rt(int u,int fa){
int max_part=0;
Size[u]=1;
for(int i=head[u],v;i;i=e[i].next){
v=e[i].to;
if(vis[i]||v==fa)continue;
get_rt(v,u);
Size[u]+=Size[v];
max_part=max(max_part,Size[v]);
}
max_part=max(nowN-Size[u],max_part);
if(max_part<maxP){
maxP=max_part;
rt=u;
}
}
void dfs(int u,int fa){
for(int i=1;i<=cnt;++i) dp[u][i]=0;
ll k=val[u],t;
for(int i=1,j=1;i<=cnt;++i){
t=kuai[i]/k;
if(t==0)break;
while(kuai[j]>t)++j;
Mod(dp[u][j],dp[fa][i]);
}
for(int i=head[u],v;i;i=e[i].next){
if(vis[i]) continue;
v=e[i].to;
if(v==fa) continue;
dfs(v,u);
for(int j=1;j<=cnt;++j) Mod(dp[u][j],dp[v][j]);
}
}
void calc(){
dp[0][1]=1;
dfs(rt,0);
for(int i=1;i<=cnt;++i) Mod(ans,dp[rt][i]);
for(int i=head[rt],v;i;i=e[i].next){
if(vis[i])continue;
v=e[i].to;
vis[i^1]=1;
nowN=Size[v];
maxP=n+5;
rt=0;
get_rt(v,0);
calc();
}
}
int main(){
int _;
scanf("%d",&_);
while(_--){
scanf("%d%d",&n,&m);
init(n);
for(int i=1;i<=n;++i)scanf("%lld",&val[i]);
for(int i=1;i<=m;i=m/(m/i)+1){
kuai[++cnt]=m/i;
}
for(int i=1,u,v;i<n;++i){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
nowN=n;
maxP=n+5;
get_rt(1,1);
calc();
printf("%lld\n",ans);
}
return 0;
}
The amount of code is concentrated at the point of partition, but you can set team
DP is well understood.