VEXOBEN
Vexoben
Mar 31, 2019
It takes 6 minutes to read this article.

题意

组数据,每组给定,,,计算

数据范围:

题解

下文中我们用代替

考虑组合意义:有个二元组和个一元组,选出任意多个二元组和所有的一元组,在其中选出个数,求方案。

假设在一元组中选出了个数,那么就要在二元组中选出个数。假设这选出的个数来自于个二元组,那么其余个二元组都可以任意选择选或不选。设表示从个二元组中选出个数,每个二元组中至少选一个数的方案数,那么答案就是:

可以直接递推:

复杂度

#include<bits/stdc++.h>
#define fi first
#define se second
#define R register
#define mp make_pair
#define pb push_back
#define LL long long
#define Ldb long double
#define pii pair<int, int>
using namespace std;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;

template <typename T> void read(T &x) {
	int f = 0;
	R char c = getchar();
	while (c < '0' || c > '9') f |= (c == '-'), c = getchar();
	for (x = 0; c >= '0' && c <= '9'; c = getchar())
		x = (x << 3) + (x << 1) + (c ^ '0');
	if (f) x = -x;
}

int n, m, k;
int inv[N], fac[N], fav[N];
int cn[N], cm[N];
int f[303][303];

int add(int x, int y) {
	static int z;
	return ((z = x + y) >= mod) ? (z - mod) : z;
}

int Qpow(int x, int p) {
	int ans = 1;
	while (p) {
		if (p & 1) ans = 1LL * ans * x % mod;
		x = 1LL * x * x % mod;
		p >>= 1;
	}
	return ans;
}

void solve() {
	read(n); read(m); read(k);
	n -= m;
	f[0][0] = 1;
	for (int i = 1; i <= k; ++i) {
		for (int j = i; j <= k; ++j) {
			f[i][j] = add(f[i - 1][j - 1], f[i - 1][j - 1]);
			if (j > 1) f[i][j] = add(f[i][j], f[i - 1][j - 2]);
		}
	}
	
	fac[0] = fav[0] = 1;
	inv[1] = fac[1] = fav[1] = 1;
	for (int i = 2; i <= k; ++i) {
		inv[i] = 1LL * -mod / i * inv[mod % i] % mod + mod;
		fac[i] = 1LL * fac[i - 1] * i % mod;
		fav[i] = 1LL * fav[i - 1] * inv[i] % mod;
	}fuzadu
	
	cn[0] = 1;
	for (int i = 1; i <= k; ++i) {
		cn[i] = 1LL * cn[i - 1] * (n - i + 1) % mod;	
	}
	for (int i = 1; i <= k; ++i) {
		cn[i] = 1LL * cn[i] * fav[i] % mod;
	}
	cm[0] = 1;
	for (int i = 1; i <= k; ++i) {
		cm[i] = 1LL * cm[i - 1] * (m - i + 1) % mod;
	}
	for (int i = 1; i <= k; ++i) {
		cm[i] = 1LL * cm[i] * fav[i] % mod;
	}
	
	int ans = 0;
	for (int i = 0; i <= k && i <= n; ++i) {
		int pw = 1LL * cn[i] * Qpow(2, m) % mod;
		for (int j = 0; j <= k && j <= m; ++j) {
			ans = add(ans, 1LL * pw * f[j][k - i] % mod * cm[j] % mod);
			pw = 1LL * pw * inv[2] % mod;
		}
	}
	cout << ans << endl;
}

int main() {
	int T;
	read(T);
	while (T--) solve();
	return 0;
}