[Explanations] CJOI2019 culmination of chicken habitat (Prufer sequence number + Sterling)

[Explanations] CJOI2019 culmination of chicken habitat (Prufer sequence number + Sterling)

Topic background

  舒服了。

Title Description

You have an n points unrooted trees, each point has a label (1 ~ n).
Now you know, there are a total of m leaf nodes, the number of trees required different forms program.
The answer to \ (9 + 10 ^ 7 \) modulo.

Here are some possible useful definition:
Leaf: degree of point 1.
Different: If the two numbers of the same tree \ (Tl = (V, E_1), T2 = (V, E_2) \) , \ (Tl \ NEQ T2 \) if and only if there exists \ ((u, v) \ in E_1, (u, v ) \ notin E_2 \)

Input Format

A total line, the first line contains two numbers n, m denote the total number of points and number of leaves.
Data must exist to ensure the tree.

Output Format

A line integer, the answer to the output (9 + 10 ^ 7 \) \ modulo results.

Sample input 1

5 3

Sample Output 1

60

Subtasks

For \ (10 \% \) data, to ensure \ (n, m <= 5
\) to \ (20 \% \) data, to ensure \ (n, m <= 10
\) to \ (40 \% \) data, to ensure \ (n, m <= 20
\) to \ (60 \% \) data, to ensure \ (n, m <= 5000
\) for the additional \ (10 \% \) data, ensure \ (m = 2 \)
for the additional \ (10 \% \) data, to ensure \ (m = n-1 \
) for the additional \ (10 \% \) data, to ensure \ (n- m> = 5 \)
to \ (100 \% \) data, to ensure \ (n, m <= 2 \ times 10 ^ 5 \)

\(Solution\)

Enumeration of the tree to be converted by the one-Prufer sequence, and then solved in accordance with a second Stirling Prufer sequence number.

Prufer sequence

Suppose there is obtained a reference tree \ (T \) , we can get a sequence by such operation, the sequence and its corresponding tree is one to one. That is, any two different legal Prufer sequence will correspond to two different trees. He noted that the trees here are numbered.

In the tree, select a minimum number of leaf nodes, the parent node is added to it Prufer sequences, and deleting the leaf node.

Up until only two nodes (only one side is not identified), can be determined at this time has the form of whole tree.

So is obtained a number \ (n-2 \) th sequence, and this sequence tree form one correspondence. Then this \ (n-2 \) sequence elements may constitute
\ [n ^ {n-2
} \] combinations.

According to the law of correspondence, that is to say there are n nodes in the tree with no reference numeral total \ (n ^ {n-2 } \) combinations .

We look at the significance of the sequence, a number of times that it appears -1 degree in Prufer sequence in the node. So now the question becomes, I want to assure \ (m \) nodes does not appear in Prufer the sequence.

Stirling number of second kind

\ (\ begin {Bmatrix} n \\ m \ end {Bmatrix} \) represents \ (n-\) elements are divided into \ (m \) non-empty set program number.

The message here is hidden: the elements are different, a collection of no distinction.

Recurrence formula

\[ {n \brace m}={n-1 \brace m-1}+m{n-1 \brace m} \]

Proof: See yyb blog.

Inclusion and exclusion \ (O (n) \) , or NTT \ (O (n-\ log n-) \) (seeking a)

\[ S_2(n,m)=\begin{Bmatrix}n\\m\end{Bmatrix}=\frac 1 {m!} \sum_{i=0}^m (-1)^i{(m-i)^n}{m\choose i} \]

Proof: See yyb blog.

Final answer
\ [(nm)! \ Times
{n \ choose m} \ times {n-2 \ brace nm} \] because the Stirling numbers of the last box (set) no difference, however, is different here , so it should be multiplied by \ ((nm)! \) make it up.

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}
const int mod=1e9+7;
const int maxn=2e5+5;
int jc[maxn];
int inv[maxn];
int n,m,ans,k;

typedef const int& ct;
inline int ksm(int base,ct p){
      register int ret=1;
      for(register int t=p;t;t>>=1,base=1ll*base*base%mod)
        if(t&1) ret=1ll*ret*base%mod;
      return ret;
}

int C(int n,int m){
      if(n<m) return 0;
      return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}

int S(ct n,ct m){
      register int ret=0;
      for(register int t=0;t<=m;++t)
        if(t&1) ret=(0ll+ret-1ll*ksm(m-t,n)*C(m,t)%mod+mod)%mod;
        else ret=(0ll+ret+1ll*ksm(m-t,n)*C(m,t)%mod+mod)%mod;
      return 1ll*ret*inv[m]%mod;
}

int main(){
#ifndef ONLINE_JUDGE
      freopen("dfzjj.in","r",stdin);
      freopen("dfzjj.out","w",stdout);
#endif
      jc[0]=1;
      inv[0]=1;
      for(register int t=1;t<maxn;++t) jc[t]=1ll*jc[t-1]*t%mod,inv[t]=1ll*inv[t-1]*ksm(t,mod-2LL)%mod;
      n=qr();m=qr();
      ans=1ll*jc[n-m]*C(n,m)%mod*S(n-2,n-m)%mod;
      printf("%d\n",ans);
      return 0;
}

Guess you like

Origin www.cnblogs.com/winlere/p/10926638.html