【BZOJ2159】Crash 的文明世界

【题目链接】

【思路要点】

  • 假设现在我们有一个集合,我们希望支持向其中加入一个0,或者询问集合中所有数的\(k\)次方和。
  • 我们发现直接展开\((x+1)^k-x^k\)不是很好处理。
  • 考虑\(x^k\)的组合意义,应当为将\(k\)个不相同的物品放到\(x\)个不相同的容器中的方案数。
  • 考虑枚举恰好有\(i\)个容器被放入了物品,有\(x^k=\sum_{i=1}^{k}S(k,i)*\binom{x}{i}*i!\),其中\(S(k,i)\)表示第二类斯特林数
  • 那么\(\sum_{x\in S}x^k=\sum_{i=1}^{k}S(k,i)*i!*\sum_{x\in S}\binom{x}{i}\)。
  • 那么现在我们就只需要对于任意\(1≤i≤K\)求出\(\sum_{x\in S}\binom{x}{i}\)即可。
  • 注意到\(\binom{x+1}{i}=\binom{x}{i}+\binom{x}{i-1}\),简单树形DP即可完成统计。
  • 时间复杂度\(O(NK)\)。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 50005;
const int MAXK = 155;
const int P = 10007;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
vector <int> a[MAXN];
int n, k, f[MAXN][MAXK], g[MAXN][MAXK];
int s[MAXK][MAXK], fac[MAXK];
void dgs(int pos, int fa) {
	for (unsigned i = 0; i < a[pos].size(); i++)
		if (a[pos][i] != fa) {
			int tmp = a[pos][i];
			g[tmp][0] += f[pos][0] + g[pos][0];
			for (int j = 1; j <= k; j++)
				g[tmp][j] += f[pos][j] + g[pos][j] + f[pos][j - 1] + g[pos][j - 1];
			g[tmp][0] -= f[tmp][0];
			g[tmp][1] -= f[tmp][0] * 2 + f[tmp][1];
			for (int j = 2; j <= k; j++)
				g[tmp][j] -= f[tmp][j] + 2 * f[tmp][j - 1] + f[tmp][j - 2];
			for (int j = 0; j <= k; j++)
				g[tmp][j] = (g[tmp][j] % P + P) % P;
			dgs(a[pos][i], pos);
		}
}
void dfs(int pos, int fa) {
	f[pos][0] = 1;
	for (unsigned i = 0; i < a[pos].size(); i++)
		if (a[pos][i] != fa) {
			dfs(a[pos][i], pos);
			f[pos][0] += f[a[pos][i]][0];
			for (int j = 1; j <= k; j++)
				f[pos][j] += f[a[pos][i]][j - 1] + f[a[pos][i]][j];
		}
	for (int i = 0; i <= k; i++)
		f[pos][i] %= P;
}
int main() {
	int l, now, A, B, Q;
	read(n), read(k), read(l);
	read(now), read(A), read(B), read(Q);
	s[0][0] = fac[0] = 1;
	for (int i = 1; i <= k; i++) {
		fac[i] = fac[i - 1] * i % P;
		for (int j = 1; j <= i; j++)
			s[i][j] = (s[i - 1][j - 1] + j * s[i - 1][j]) % P;
	}
	for (int i = 1; i <= n - 1; i++) {
		now = (now * A + B) % Q;
        	int tmp = min(i, l);
        	int x = i - now % tmp, y = i + 1;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	dfs(1, 0);
	dgs(1, 0);
	for (int i = 1; i <= n; i++) {
		int ans = 0;
		for (int j = 0; j <= k; j++)
			ans += s[k][j] * fac[j] % P * (f[i][j] + g[i][j]) % P;
		writeln(ans % P);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80752396