The NN cows of Farmer John's Circus (1≤N≤1051≤N≤105) are preparing their upcoming acts. The acts all take place on a tree with vertices labeled 1…N1…N. The "starting state" of an act is defined by a number 1≤K≤N1≤K≤N and an assignment of cows 1…K1…K to the vertices of the tree, so that no two cows are located at the same vertex.
In an act, the cows make an arbitrarily large number of "moves." In a move, a single cow moves from her current vertex to an unoccupied adjacent vertex. Two starting states are said to be equivalent if one may be reached from the other by some sequence of moves.
For each 1≤K≤N1≤K≤N, help the cows determine the number of equivalence classes of starting states: that is, the maximum number of starting states they can pick such that no two are equivalent. Since these numbers may be very large, output their remainders modulo 109+7109+7.
Line 11 contains NN.Lines 2≤i≤N2≤i≤N each contain two integers aiai and bibi denoting an edge between aiai and bibi in the tree.
For each 1≤i≤N,1≤i≤N, the ii-th line of output should contain the answer for K=iK=i modulo 109+7109+7.
5 1 2 2 3 3 4 3 5
1 1 3 24 120
For K=1K=1 and K=2,K=2, any two states can be transformed into one another.
Now consider K=3K=3, and let cici denote the location of cow ii. The state (c1,c2,c3)=(1,2,3)(c1,c2,c3)=(1,2,3) is equivalent to the states (1,2,5)(1,2,5) and (1,3,2).(1,3,2). However, it is not equivalent to the state (2,1,3).(2,1,3).
8 1 3 2 3 3 4 4 5 5 6 6 7 6 8
1 1 1 6 30 180 5040 40320
Problem credits: Dhruv Rohatgi
[/hide]
(Analysis by Benjamin Qi)
In the following tree diagrams, - and | denote edges of the tree, * denotes an unoccupied vertex, and ? denotes an occupied vertex.
For K=NK=N the answer is always N!.N!. Now let's consider the case K<N.K<N.
Say that a state is in "normalized" if the cows occupy vertices 1…K1…K. Clearly any state can be normalized via a series of moves. Call two normalized states "friends" if one is reachable from the other. The number of friends for each state must be the same. The answer will equal K!K! over the number of friends of any normalized state with KK cows has.
For any two cows xx and yy in the normalized state, we wish to know whether we can swap xx and yy while leaving all other cows in the same vertices. The goal is to move until the tree contains the following as a subgraph:
* | | x--*--y
Then you can swap xx and yy and undo all the moves made up to this point to re-normalize the state.
Consider the following method that moves xx and yy into the above state if possible, or otherwise states that it is impossible to swap xx and yy.
x--*--*--*--z--y ?--*--*--*--z--y | -> | | | ? x
x--*--*--z--y | | ?
* z | | | -> | *--x--z--y x--*--*--y
Let's further examine the case where it is impossible to swap xx and yy. Call a vertex "intermediate" if it has degree 2. Move xx such that is adjacent to zz, and suppose that the shortest path with non-intermediate endpoints that contains edge x↔zx↔z at the time of termination is (a,b)(a,b); call this the extension of x↔zx↔z.
Let AA be the size of the subtree of aa when the tree is rooted at bb and define BB similarly. We can show that if xx and yy can't be swapped, then K≥(A−1)+(B−1).K≥(A−1)+(B−1). In fact, there will be
vertices that always remain on the (a,b)(a,b) path (and their relative order on the path can never change). Plus, cows that are in the subtree of aa rooted at bb excluding aa can never reach the subtree of bb rooted at aa excluding bb, and vice versa. For example, consider the following (a,b)(a,b) extension:
. . | | | | a--.--b | | | | . . | | .
In the following situation, K=(A−1)+(B−1)K=(A−1)+(B−1), so none of {1,2,3}{1,2,3} can swap with any of {4,5}{4,5}.
1 4 | | | | *--*--* | | | | 2 5 | | 3
In the following situation, K=(A−1)+(B−1)+1K=(A−1)+(B−1)+1, so 66 cannot leave the a↔ba↔b path.
1 4 | | | | 6--*--* | | | | 2 5 | | 3
Call every edge on each such extension "saturated," and the cows that are constrained to some extension "stuck."
Now consider each connected component that remains after removing all saturated edges. Suppose that connected component cc contains exactly xx unsaturated edges and is adjacent to exactly yy saturated edges. To compute the number of non-stuck cows within cc, we should start with KK and then subtract some quantity for each adjacent saturated edge.
For the extension (a,b)(a,b) of each adjacent saturated edge, let aa be the vertex outside the component and bb be the vertex inside the component. Then number of vertices removed from the component by this edge is equal to
If we sum this over all adjacent saturated edges, the result will be
The number of cows in cc is KK minus this expression, or sc=(N−1−K)(y−1)+xsc=(N−1−K)(y−1)+x. Note that when y=0,y=0, all of the vertices are in the same connected component and sc=K−(N−1)+(N−1)=K,sc=K−(N−1)+(N−1)=K, which makes sense since no cows are stuck.
For any friend, the stuck cows must remain in the same relative positions. However, the unstuck cows in each component mentioned above can permute themselves arbitrarily. So the number of friends of each state is ∏csc!∏csc! and the answer will be K!∏csc!.K!∏csc!.
We can compute this expression for all KK in decreasing order. For each path that transitions from saturated to unsaturated when KK is decremented, we can update xx and yy for the resulting combined component with the "Disjoint Set Union" data structure. Furthermore, the sum of the number of components over all 1≤K<N1≤K<N is equal to
so we can afford to iterate over all of the components for each KK to compute ∏csc!∏csc!. This solution runs in O(NlogN)O(NlogN) or O(Nα(N)),O(Nα(N)), depending on the implementation.
#include <bits/stdc++.h> using namespace std; #define f first #define s second typedef long long ll; const int MOD = 1e9+7; const int MX = 1e5+5; void setIO(string s) { ios_base::sync_with_stdio(0); cin.tie(0); freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } struct mi { int v; explicit operator int() const { return v; } mi() { v = 0; } mi(ll _v):v(_v%MOD) { v += (v<0)*MOD; } }; mi& operator+=(mi& a, mi b) { if ((a.v += b.v) >= MOD) a.v -= MOD; return a; } mi& operator-=(mi& a, mi b) { if ((a.v -= b.v) < 0) a.v += MOD; return a; } mi operator+(mi a, mi b) { return a += b; } mi operator-(mi a, mi b) { return a -= b; } mi operator*(mi a, mi b) { return mi((ll)a.v*b.v); } mi& operator*=(mi& a, mi b) { return a = a*b; } vector<int> invs, fac, ifac; void genFac(int SZ) { invs.resize(SZ), fac.resize(SZ), ifac.resize(SZ); invs[1] = fac[0] = ifac[0] = 1; for (int i = 2; i < SZ; ++i) invs[i] = MOD-(ll)MOD/i*invs[MOD%i]%MOD; for (int i = 1; i < SZ; ++i) { fac[i] = (ll)fac[i-1]*i%MOD; ifac[i] = (ll)ifac[i-1]*invs[i]%MOD; } } ll comb(int a, int b) { if (a < b || b < 0) return 0; return (ll)fac[a]*ifac[b]%MOD*ifac[a-b]%MOD; } int N, par[MX]; vector<int> adj[MX]; mi ans[MX]; pair<int,int> cur[MX]; vector<pair<int,pair<int,int>>> ed; set<int> con; struct DSU { vector<int> e; void init(int n) { e = vector<int>(n,-1); } int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); } bool unite(int len, int x, int y) { // union-by-rank x = get(x), y = get(y); assert(x != y); if (e[x] > e[y]) swap(x,y); e[x] += e[y]; e[y] = x; assert(con.count(y)); con.erase(y); cur[x].f += cur[y].f-2; cur[x].s += cur[y].s+len; return 1; } }; DSU D; void dfs(int x) { for (int t: adj[x]) if (t != par[x]) { par[t] = x; dfs(t); } } void dfs(int x, int lst, int d) { if (adj[x].size() != 2) { if (lst) ed.push_back({d,{x,lst}}); d = 0; lst = x; } for (int y: adj[x]) if (y != par[x]) { par[y] = x; dfs(y,lst,d+1); } } int main() { setIO("circus"); cin >> N; genFac(N+1); for (int i = 0; i < N-1; ++i) { int a,b; cin >> a >> b; adj[a].push_back(b), adj[b].push_back(a); } int root = 1; while (adj[root].size() == 2) root ++; dfs(root,0,0); sort(begin(ed),end(ed)); for (int i = 1; i <= N; ++i) if (adj[i].size() != 2) { cur[i] = {adj[i].size(),0}; con.insert(i); } ans[N] = fac[N]; int ind = 0; D.init(N+1); for (int k = N-1; k > 0; --k) { while (ind < ed.size() && N-1-ed[ind].f > k) { D.unite(ed[ind].f,ed[ind].s.f,ed[ind].s.s); ind ++; } mi ret = fac[k]; for (int t: con) ret *= ifac[(N-1-k)*(cur[t].f-1)+cur[t].s]; ans[k] = ret; } for (int i = 1; i <= N; ++i) cout << ans[i].v << "\n"; }
[/hide]
© 2024. All Rights Reserved. 沪ICP备2023009024号-1