>
众所周知,小葱同学擅长计算,尤其擅长计算组合数。小葱现在希望你计算
的值。其中 , , 为给定的整数, 为给定的一个 次多项式 。 为组合数,其值为 。
下降幂能解决很多与组合数有关的问题,看到多项式/幂,先冲上去用斯特林数转下降幂多项式。
把 用第二类斯特林数变成 的形式。
交换枚举顺序:
设 的 ,则 等于:
带入原式,得:
把下降幂和组合数相乘:
交换枚举顺序:
设 ,原式化为:
没有意义,使用二项式定理:
可以在 的时间复杂度内预处理出,总时间复杂度 。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
int x = 0, f = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) f -= (ch == '-') * 2;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * f;
}
const int N = 2010;
int n, m, x, mod;
int fact[N], a[N], b[N], g[N], s[N][N], facinv[N];
int qpow(int a, int b) {
int res = 1 % mod;
for (; b; b >>= 1) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
}
return res;
}
signed main() {
n = read(), x = read(), mod = read(); m = read();
fact[0] = facinv[0] = 1;
for (int i = 1; i <= m; i ++ ) fact[i] = fact[i - 1] * i % mod;
facinv[m] = qpow(fact[m], mod - 2);
for (int i = m - 1; i >= 1; i -- ) facinv[i] = facinv[i + 1] * (i + 1) % mod;
for (int i = 0; i <= m; i ++ ) a[i] = read();
if (m == 0) printf("%lld\n", a[0] * qpow(x + 1, n) % mod);
else {
int ans = 0;
s[0][0] = 1;
for (int i = 1; i <= m; i ++ ) {
for (int j = 1; j <= i; j ++ ) {
s[i][j] = (s[i - 1][j - 1] + s[i - 1][j] * j) % mod;
}
}
for (int i = 0; i <= m; i ++ ) {
for (int j = i; j <= m; j ++ ) {
b[i] = (b[i] + a[j] % mod * s[j][i] % mod) % mod;
}
}
g[0] = 1;
for (int i = 1; i <= m; i ++ ) g[i] = g[i - 1] * (n - i + 1) % mod;
for (int i = 0; i <= m; i ++ ) {
int res = g[i] * b[i] % mod * qpow(x, i) % mod * qpow(x + 1, n - i) % mod;
ans = (ans + res) % mod;
}
printf("%lld\n", ans);
}
return 0;
}
Crash 小朋友最近迷上了一款游戏——文明5 (Civilization V)。在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家。
现在 Crash 已经拥有了一个 个城市的国家,这些城市之间通过道路相连。由于建设道路是有花费的,因此 Crash 只修建了 条道路连接这些城市,不过可以保证任意两个城市都有路径相通。
在游戏中,Crash 需要选择一个城市作为他的国家的首都,选择首都需要考虑很多指标,有一个指标是这样的:
其中 表示第 个城市的指标值, 表示第 个城市到第 个城市需要经过的道路条数的最小值, 为一个常数且为正整数。
因此 Crash 交给你一个简单的任务:给出城市之间的道路,对于每个城市,输出这个城市的指标值,由于指标值可能会很大,所以你只需要输出这个数 的值。
交换枚举顺序: