简单题,随便写写吧。
问题等价于对所有从第 \(0\) 行上某个点到 \((n,m)\) 的路径,满足第一步是向上的,计算它们的 \(y^k\) 之和,其中 \(y\) 为起点纵坐标。因此首先考虑列出式子:
\[ans=\sum\limits_{i=1}^ni^k·\dbinom{n-i+m-1}{m-1}
\]
由于此题 \(n,k\) 数据范围相对来说都比较大,因此直接求 / 斯特林拆幂貌似都不太可做,因此考虑从数据范围较小的 \(m\) 入手。注意到,下底数固定的组合数事实上也是多项式,即 \(\dbinom{n-i+m-1}{m-1}\) 是关于 \(i\) 的最高项为 \(x^{m-1}\) 的多项式,而由于 \(m\) 很小,该系数可以暴力 \(m^2\) 求。
于是问题转化为,求一个 \(m+k\) 次多项式在 \(n\) 处的前缀和。注意到,虽然这个 \(m+k\) 次多项式最高次数较高,但是系数非零的项不多,因此可以直接对这些项进行插值,复杂度 \(\Theta(m(m+k))\),当然也可以使用多项式 inv 一次性对所有 \(i\in[1,m+k]\) 求 \(\sum\limits_{j=1}^nj^i\),时间复杂度 \(\Theta((m+k)\log (m+k))\),但对于此题来说没有必要,甚至因为模数是 \(10^9+7\) 而显得有些累赘。
const int MAXN = 2.5e6 + 33;
const int MOD = 1e9 + 7;
int qpow(int x, int e) {
int ret = 1;
for (; e; e >>= 1, x = 1ll * x * x % MOD)
if (e & 1) ret = 1ll * ret * x % MOD;
return ret;
}
ll n; int m, k;
int pw[MAXN + 5], sum[MAXN + 5], pre[MAXN + 5], suf[MAXN + 5];
int fac[MAXN + 5], ifac[MAXN + 5];
void init_fac(int n) {
for (int i = (fac[0] = ifac[0] = ifac[1] = 1) + 1; i <= n; i++)
ifac[i] = 1ll * ifac[MOD % i] * (MOD - MOD / i) % MOD;
for (int i = 1; i <= n; i++) {
fac[i] = 1ll * fac[i - 1] * i % MOD;
ifac[i] = 1ll * ifac[i - 1] * ifac[i] % MOD;
}
}
int pr[MAXN + 5], prcnt = 0, mnp[MAXN + 5], vis[MAXN + 5];
void sieve(int n) {
for (int i = 2; i <= n; i++) {
if (!vis[i]) pr[++prcnt] = i, mnp[i] = i;
for (int j = 1; j <= prcnt && pr[j] * i <= n; j++) {
vis[pr[j] * i] = 1; mnp[pr[j] * i] = pr[j];
if (i % pr[j] == 0) break;
}
}
}
vector<int> conv(vector<int> a, vector<int> b) {
vector<int> res(a.size() + b.size() - 1, 0);
for (int i = 0; i < a.size(); i++) for (int j = 0; j < b.size(); j++)
res[i + j] = (res[i + j] + 1ll * a[i] * b[j]) % MOD;
return res;
}
int calc(ll n) {
n %= MOD; int res = 0;
for (int i = 1; i <= k + m + 2; i++) pw[i] = 1ll * pw[i] * i % MOD;
for (int i = 1; i <= k + m + 2; i++) sum[i] = (sum[i - 1] + pw[i]) % MOD;
pre[0] = suf[k + m + 3] = 1;
for (int i = 1; i <= k + m + 2; i++) pre[i] = 1ll * pre[i - 1] * (n - i + MOD) % MOD;
for (int i = k + m + 2; i; i--) suf[i] = 1ll * suf[i + 1] * (n - i + MOD) % MOD;
for (int i = 1; i <= k + m + 2; i++) {
int coef = 1ll * ifac[i - 1] * ifac[k + m + 2 - i] % MOD;
coef = 1ll * coef * pre[i - 1] % MOD * suf[i + 1] % MOD;
if ((k + m + 2 - i) & 1) coef = MOD - coef;
res = (res + 1ll * coef * sum[i]) % MOD;
}
return res;
}
int main() {
sieve(MAXN); init_fac(MAXN); scanf("%lld%d%d", &n, &m, &k);
if (!m) return printf("%d\n", qpow(n % MOD, k)), 0;
pw[1] = 1;
for (int i = 2; i <= k + m + 2; i++) if (!vis[i]) pw[i] = qpow(i, k - 1);
for (int i = 2; i <= k + m + 2; i++) if (vis[i]) pw[i] = 1ll * pw[mnp[i]] * pw[i / mnp[i]] % MOD;
--m; vector<int> F; F.pb(ifac[m]); int ans = 0;
for (int i = 0; i < m; i++) F = conv(F, vector<int>{m + n % MOD - i, MOD - 1});
// for (int i = 0; i <= m; i++) printf("%d\n", 1ll * F[i] * 24 % MOD);
for (int i = 0; i <= m; i++) ans = (ans + 1ll * calc(n) * F[i]) % MOD;
printf("%d\n", ans);
return 0;
}