首先是两个众所周知的结论:

杨辉三角代表了组合数,而杨辉三角中第 nn 行就是

C(n1,k)C(n-1,k)

其中 k[0,n1]k\in[0,n-1],这 nn 个数。

另外一个就是组合数的公式:

C(n,m)=n!m!(nm)!C(n,m)=\dfrac{n!}{m!(n-m)!}

有了这两个结论,再一看数据范围 n106n\le10^6,一个合理的 O(n)O(n) 做法就随之而生。

下面介绍一下【模逆元】的相关知识。

求阶乘逆元,线性时间内算出 1!n!modP1!\sim n!\mod P 的逆元。

首先根据 faci=faci1×imodPfac_i=fac_{i-1}\times i\mod P 求出 1!n!modP1!\sim n!\mod P 的值。

随后根据 Fermat 小定理,求出 n!modPn!\mod P 的逆元:(n!modP)P2modP(n!\mod P)^{P-2}\mod P

Fermat 小定理:(pp 必须是素数)

apa(mod p)a^{p}\equiv a(\bmod~p)

根据这个,不难得到:

a1ap2(mod p)a^{-1}\equiv a^{p-2}(\bmod~p)

最后根据 facinvi=facinvi+1×imodPfacinv_i=facinv_{i+1}\times i\mod P 求出 1!(n1)!modP1!\sim (n-1)!\mod P 的逆元即可。

复杂度 O(n)+O(logn)+O(n)=O(n)O(n)+O(\log n)+O(n)=O(n)

/*
根据杨辉三角的组合意义,第 i 行的数分别是 C(i-1, k)
而 C(n, m) = n! / m! / (n-m)! 
既然你 n 才 1e6,我直接预处理阶乘就好了
*/
#include<cstdio>
int init(){
	char c = getchar();
	int x = 0, f = 1;
	for (; c < '0' || c > '9'; c = getchar())
		if (c == '-') f = -1;
	for (; c >= '0' && c <= '9'; c = getchar())
		x = (x << 1) + (x << 3) + (c ^ 48);
	return x * f;
}
void print(int x){
	if (x < 0) x = -x, putchar('-');
	if (x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int N = (int) 1e6 + 5, Mod = (int) 1e9 + 7;
int quick_mod(int a, int b){
	int s = 1;
	while (b) {
		if (b & 1) s = s * 1ll * a % Mod;
		a = a * 1ll * a % Mod; b >>= 1;
	}
	return s;
}
int fac[N], facinv[N];
int C(int n, int m){
	return fac[n] * 1ll * facinv[m] % Mod * 1ll * facinv[n - m] % Mod;
}
int main(){
	int n = init();
	fac[0] = 1;
	for (int i = 1; i < N; ++i)
		fac[i] = fac[i - 1] * 1ll * i % Mod;
	facinv[N - 1] = quick_mod(fac[N - 1], Mod - 2);
	for (int i = N - 2; i >= 0; --i)
		facinv[i] = facinv[i + 1] * 1ll * (i + 1) % Mod;
	int ans = 1;
	for (int k = 0; k < n; ++k)
		ans = ans * 1ll * C(n - 1, k) % Mod;
	print(ans), putchar('\n');
}