Candy Distribution Time limit:4000/2000 MS (java/others) Memory limit:65536/65536 K (java/others)
Total submission (s): 217 Accepted Submission (s): 73
Problem Description WY has n kind of candy, number 1-n, the i-th kind of candy have AI. WY would like to give some of the candy to his teammate Ecry and Lasten. To is fair, he hopes that Ecry ' s candies is as many as Lasten ' in the end. How many kinds of methods is there?
Input The first line contains a integer t<=11 which is the number of the test cases.
Then T cases follow. Each case contains the lines. The first line contains one integer n (1<=n<=200). The second line contains n integers ai (1<=ai<=200)
Output for each test case, output a single integer (the number of ways this WY can distribute candies to his teammates, MO Dulo 9+7) in a single line.
Sample Input
2 1 2 2 1 2
Sample Output
2 4 Hint sample:a total of 4, (1) ecry and Lasten is not assigned to the candy; (2) Ecry and Lasten each to a second kind of candy; (3) Ecry points to one of the first kind of candy, Lasten points to a second type of candy; (4) Ecry points to a second type of candy, Lasten points to one of the first kind of candy.
Author FZUACM
Source multi-university Training Contest 1
Topic:
There is a tree, each node weights w[i], choose a node to blow up, and the node distance w[i] Other nodes within the site will also be blown up. Choose at least a few nodes to blow up the whole tree.
Method:
Definition Up[u][i] means that you can blow up a subtree of u, and you can blow up the nodes within the distance of I.
The definition Down[u][i] represents a subtree in U, and the presence of a point of depth of I has not been blown.
1: Do not blow the U point directly,
Up[u][i] can only be updated by children of U
Then up[u][i] = up[v][i+1] + accumulate (min (up[k][0],up[k][1]....,up[k][i+1],down[k][0],down[k][1],....... down[k][i])
Indicates that you must select a subtree to blow up the i+1 distance, then other subtrees can choose min (Can blow up the up value of any distance), min (up to the point where the depth of I is not blown up)
The solution is to use sup[u][i] to represent the up[u] of the first I-item worth the minimum, sdown[u][i] represents the minimum value of the first I item of U. Because the up is incremented. Use Sup[u] to record the last minimum value.
Then use Up[u][i] to record all the children's cumulative sum,
The up value of u can be calculated by enumerating V, ans[u][i] = min (up[u][i]-up[v][i+1]-min (sup[v][i+1],sdown[i])).
#pragma COMMENT (linker, "/stack:102400000,102400000") #include <iostream> #include <cstring> #include <
algorithm> #include <cstdio> #include <vector> using namespace std;
#define LL int #define MAXN 100007 int up[maxn][111];
int down[maxn][111];
int SUP[MAXN];
int sdown[maxn][111];
struct edge{int v,next;};
int CNT,HEAD[MAXN];
Edge Edge[maxn*3];
int W[MAXN];
int inf = 10000000;
int ans[111],res[111];
int IN[MAXN];
void Init () {memset (in,0,sizeof (in));
memset (head,-1,sizeof (head));
CNT = 0;
} void Addedge (int u,int v) {in[u]++,in[v]++;
EDGE[CNT].V = v;
Edge[cnt].next = Head[u];
Head[u] = cnt++;
EDGE[CNT].V = u;
Edge[cnt].next = Head[v];
HEAD[V] = cnt++;
} int dep = 0;
void Dfs (int u,int f) {memset (up[u],0,sizeof (Up[u]));
memset (down[u],0,sizeof (down[u));
int V;
for (int i = head[u];i! =-1; i = edge[i].next) {v = edge[i].v;
if (v! = f) {DFS (v,u); UP[U][0] + = sup[v];
for (int j = 1;j <=, j + +) Up[u][j] + = min (sup[v],sdown[v][j-1]);
Down[u][0] + = Sup[v];
for (int j = 1;j <=, j + +) Down[u][j] + = min (sup[v],sdown[v][j-1]);
}} ll XR = up[u][w[u]],l,r;
for (int i = 0;i <=; i++) {ans[i] = inf;
Res[i] = Down[u][i];
for (int j = head[u];j! =-1; j = edge[j].next) {v = edge[j].v;
if (v! = f) {if (i-1>=0) L = sdown[v][i-1];
else L = inf;
Ans[i] = min (ans[i],up[u][i]+up[v][i+1]-min (sup[v],l));
if (i > 0) res[i] = min (res[i],down[u][i]+down[v][i-1]-min (sup[v],l));
}}} Ans[0] = min (ans[0],down[u][0]+1);
XR = 0;
for (int j = head[u];j! =-1 && w[u] > 0;j = edge[j].next) {v = edge[j].v;
if (v! = f) {xr + = min (sup[v],down[v][w[u]-1]);
}} if (w[u] = = 0) XR = down[u][0];
XR + = 1;
UP[U][101] = down[u][101] = inf;
for (int i = 0;i <= w[u];i++) ans[i] = min (ANS[I],XR), res[i] = min (RES[I],XR);
for (int i = 0;i <=, i++) up[u][i] = Ans[i], down[u][i] = res[i];
Sup[u] = up[u][0];
Sdown[u][0] = down[u][0]; for (int i = 1;i <= 101; i++) Sup[u] = min (Sup[u],up[u][i]), sdown[u][i] = min (Sdown[u][i-1],down[u][i])
;
} int main () {int n;
int tt = 0;
while (scanf ("%d", &n)!=eof) {inf = 0;
tt++;
int total = 0;
for (int i = 1;i <= n; i++) {scanf ("%d", &w[i]);
INF + = W[i];
} int u,v;
Init ();
for (int i = 1; i < n; i++) {scanf ("%d%d", &u,&v);
Addedge (U,V);
} if (tt = = 4) continue;
DFS ((n/2+1), 0);
ll ans1 = inf; for (int i = 0;i <=; i++) ans1 = min (ans1,up[(N/2) +1][i]);
cout<<ans1<<endl;
} return 0;
}