上决╇ф的黑科技
上决╇ф费尽千辛万苦,终于找到了能打败Alpha Ceph的黑科技。要启动这项黑科技,是需要大量的人力和财力的。
假设这项黑科技需要n个人,那么所需的财力计算方法如下:
1、选取这n个不同的人的一个非空集合,假设选取了x个人,那么这x个人所需的工资为
x
k
x_k
xk。
2、启动这个黑科技的价格,其实就是所有的方案所需工资的总和。
现在给出N和k,上决╇ф想知道,如果这项黑科技所需的人数分别为1−N时,所需的财力。
由于上决╇ф比较穷,只要求输出所需财力对 1 0 9 + 7 10^9+7 109+7取模的结果。
Input
输入只包含两个整数
N
,
k
(
1
≤
N
≤
1
0
5
,
1
≤
k
≤
2
31
−
1
)
N,k(1\leq N\leq 10^5,1\leq k \leq 2^{31}-1)
N,k(1≤N≤105,1≤k≤231−1)意义与描述中相同。
Output
输出一行,N个数,用空格隔开。第i个数代表所需i个人时的总财力对
1
0
9
+
7
10^9+7
109+7取模。
题解
首先根据题意,所需人数为n时
a
n
s
=
∑
i
=
1
n
i
k
C
n
i
ans=\sum_{i=1}^{n}i^kC_n^i
ans=i=1∑nikCni
我们写成
∑
n
=
1
N
∑
i
=
1
n
i
k
C
n
i
∑
n
=
1
N
∑
i
=
1
n
i
k
n
!
(
n
−
i
)
!
i
!
∑
n
=
1
N
n
!
∑
i
=
1
n
i
k
(
n
−
i
)
!
i
!
\begin{aligned} &\sum_{n=1}^{N}\sum_{i=1}^{n}i^kC_n^i\\ &\sum_{n=1}^{N}\sum_{i=1}^{n}i^k\cfrac{n!}{(n-i)!i!}\\ &\sum_{n=1}^{N}n!\sum_{i=1}^{n}\cfrac{i^k}{(n-i)!i!} \end{aligned}
n=1∑Ni=1∑nikCnin=1∑Ni=1∑nik(n−i)!i!n!n=1∑Nn!i=1∑n(n−i)!i!ik
太大了,只能卷积里面的
∑
i
=
1
n
i
k
(
n
−
i
)
!
i
!
\sum_{i=1}^{n}\cfrac{i^k}{(n-i)!i!}
i=1∑n(n−i)!i!ik
我们将其分成
i
k
i
!
⋅
1
(
n
−
i
)
!
\cfrac{i^k}{i!}·\cfrac{1}{(n-i)!}
i!ik⋅(n−i)!1成为卷积形式
(
f
∗
g
)
(
x
)
=
∑
i
=
1
n
f
(
x
)
g
(
x
−
i
)
(f*g)(x)=\sum_{i=1}^{n}f(x)g(x-i)
(f∗g)(x)=∑i=1nf(x)g(x−i)
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <math.h>
#include <unordered_map>
//#include <tr1/unordered_map>
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 300005;
const int INF = 0x3f3f3f3f;
const double eps = 1e-06;
const double PI = acos(-1);
int mod;
namespace Math {
inline int pw(int base, int p, const int mod) {
static int res;
for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
return res;
}
inline int inv(int x, const int mod) { return pw(x, mod - 2, mod); }
}
using namespace Math;
const int mod1 = 998244353, mod2 = 1004535809, mod3 = 469762049, G = 3;
const long long mod_1_2 = static_cast<long long> (mod1) * mod2;
const int inv_1 = inv(mod1, mod2), inv_2 = inv(mod_1_2 % mod3, mod3);
struct Int {
int A, B, C;
explicit inline Int() { }
explicit inline Int(int __num) : A(__num), B(__num), C(__num) { }
explicit inline Int(int __A, int __B, int __C) : A(__A), B(__B), C(__C) { }
static inline Int reduce(const Int &x) {
return Int(x.A + (x.A >> 31 & mod1), x.B + (x.B >> 31 & mod2), x.C + (x.C >> 31 & mod3));
}
inline friend Int operator + (const Int &lhs, const Int &rhs) {
return reduce(Int(lhs.A + rhs.A - mod1, lhs.B + rhs.B - mod2, lhs.C + rhs.C - mod3));
}
inline friend Int operator - (const Int &lhs, const Int &rhs) {
return reduce(Int(lhs.A - rhs.A, lhs.B - rhs.B, lhs.C - rhs.C));
}
inline friend Int operator * (const Int &lhs, const Int &rhs) {
return Int(static_cast<long long> (lhs.A) * rhs.A % mod1, static_cast<long long> (lhs.B) * rhs.B % mod2, static_cast<long long> (lhs.C) * rhs.C % mod3);
}
inline int get() {
long long x = static_cast<long long> (B - A + mod2) % mod2 * inv_1 % mod2 * mod1 + A;
return (static_cast<long long> (C - x % mod3 + mod3) % mod3 * inv_2 % mod3 * (mod_1_2 % mod) % mod + x) % mod;
}
} ;
#define maxn 131072
namespace Poly {
#define N (maxn << 1)
int lim, s, rev[N];
Int Wn[N | 1];
inline void init(int n) {
s = -1, lim = 1; while (lim < n) lim <<= 1, ++s;
for (register int i = 1; i < lim; ++i) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
const Int t(pw(G, (mod1 - 1) / lim, mod1), pw(G, (mod2 - 1) / lim, mod2), pw(G, (mod3 - 1) / lim, mod3));
*Wn = Int(1); for (register Int *i = Wn; i != Wn + lim; ++i) *(i + 1) = *i * t;
}
inline void NTT(Int *A, const int op = 1) {
for (register int i = 1; i < lim; ++i) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
for (register int mid = 1; mid < lim; mid <<= 1) {
const int t = lim / mid >> 1;
for (register int i = 0; i < lim; i += mid << 1) {
for (register int j = 0; j < mid; ++j) {
const Int W = op ? Wn[t * j] : Wn[lim - t * j];
const Int X = A[i + j], Y = A[i + j + mid] * W;
A[i + j] = X + Y, A[i + j + mid] = X - Y;
}
}
}
if (!op) {
const Int ilim(inv(lim, mod1), inv(lim, mod2), inv(lim, mod3));
for (register Int *i = A; i != A + lim; ++i) *i = (*i) * ilim;
}
}
#undef N
}
using namespace Poly;
const int N = 1e6;
int n, k;
Int A[maxn << 1], B[maxn << 1];
ll F[N+10],Finv[N+10];
int main() {
scanf("%d%d", &n, &k);
mod = 1e9+7;
n++;
F[0]=1;
for(int i = 1; i <= N; ++i) F[i] = F[i-1]*i%mod;
Finv[N] = pw(F[N],mod-2,mod);
for(int i = N-1; i >= 0; --i) Finv[i] = Finv[i+1]*(i+1)%mod;
for(int i = 0; i < n; ++i) A[i] = Int((int)(Finv[i]*pw(i,k,mod)%mod));
for(int i = 0; i < n; ++i) B[i] = Int((int)Finv[i]);
init(n+n);
NTT(A),NTT(B);
for(int i = 0; i < lim; ++i) A[i] = A[i]*B[i];
NTT(A,0);
for(int i = 1; i < n; ++i)
printf("%lld%c",(ll)A[i].get()%mod*F[i]%mod,i == n-1 ? '\n' : ' ');
return 0;
}
/*
*/