51nod1251 fox序列的数量(生成函数)

51nod1251 fox序列的数量(生成函数)

题目大意

一个不下降的序列被称为 Fox 序列,当且仅当序列里边出现频率最高的元素是唯一的。

例如:序列 1, 1, 2, 3, 4 是一个 Fox 序列, 因为它符合定义。出现频率最高的元素是1,它出现了2次,并且没有别的元素出现的次数为2。

但是序列 1, 1, 2, 2 不是 Fox 序列, 因为1 和 2 都出现了2次,不是唯一的。

注意: 序列 2, 1, 1 不是 Fox 序列, 因为他不是不下降序列。

给出N,M,计算有多少个长度为N的 Fox 序列,满足序列的所有元素都 >= 1并且 <= M。由于结果很大,输出Mod 1000000007的结果。

例如:N = 3,M = 2。满足条件的序列为:1 1 1, 2 2 2, 1 1 2, 1 2 2,共4个。

数据范围

第1行:一个数T,表示输入的测试数量(1 <= T <= 20)
第2 - T + 1行:每行2个数,N和M,中间用空格分隔(1 <= N, M <= 10^5)

解题思路

生成函数简单题

首先写出答案式子

\[Ans = \sum_{i=1}^nm*[n](1+x+x^2+ \cdots +x^{i-1})^{m-1}\\ = \sum_{i=1}^mm*[n]\frac {(1-x^i)^{m-1}}{(1-x)^{m-1}} \]

考虑分式上部的第 \(ik\) 项的系数是 \((-1)^k{m-1 \choose k}\),分式下部的第 k 项系数是 \({k + m - 2\choose m - 2}\)

暴力乘起来即可,复杂度是 \(\Theta(NlogN)\)

代码

const int P = 1e9+7;
const int N = 1005000;
const int lim = 200500;
ll inv[N], fac[N], T, m, n;
ll C(ll n, ll m) {
	return fac[n] * inv[m] % P * inv[n-m] % P;
}

int main() {
	inv[0] = fac[0] = inv[1] = fac[1] = 1;
	for (int i = 2;i <= lim; i++)
		inv[i] = inv[P % i] * (P - P / i) % P;
	for (int i = 2;i <= lim; i++)
		fac[i] = fac[i-1] * i % P, 
		inv[i] = inv[i-1] * inv[i] % P;
	for (read(T); T; T--) {
		read(n), read(m);
		if (m == 1) { write(1); continue; }
		ll ans = 0;
		for (int i = 2;i <= n; i++) {
			ll res = 0;
			for (int j = 0;j * i <= n - i; j++) {
				if (j & 1) res -= C(m - 1, j) * C(n - i - j * i + m - 2, m - 2);
				else res += C(m - 1, j) * C(n - i - j * i + m - 2, m - 2); res %= P;
			}
			ans = (ans + res * m) % P;
		}
		write((ans + P) % P);
	}
	return 0;
}
posted @ 2020-07-17 08:01  Hs-black  阅读(141)  评论(0编辑  收藏  举报