luoguP4389 付公主的背包
分析
神仙题系列。。。
首先写出每件商品的生成函数,假设体积为
V
V
V
A
(
x
)
=
∑
i
=
0
∞
x
i
v
=
1
1
−
x
v
A(x)=\sum_{i=0}^{\infty}x^{iv}=\frac{1}{1-x^{v}}
A(x)=∑i=0∞xiv=1−xv1
答案就是
A
n
s
(
x
)
≡
∏
1
1
−
x
v
i
(
m
o
d
x
m
+
1
)
Ans(x)\equiv\prod\frac{1}{1-x^{vi}}(mod x^{m+1})
Ans(x)≡∏1−xvi1(modxm+1)
裸跑
N
T
T
NTT
NTT就是
O
(
n
m
l
o
g
)
O(nmlog)
O(nmlog)
乘积的处理比较麻烦,尝试转化成加和,两边同时取对数
l
n
(
A
n
s
(
x
)
)
≡
∑
l
n
(
1
1
−
x
v
i
)
(
m
o
d
x
m
+
1
)
ln(Ans(x))\equiv\sum ln(\frac{1}{1-x^{v_i}})(mod x^{m+1})
ln(Ans(x))≡∑ln(1−xvi1)(modxm+1)
尝试把
l
n
(
1
1
−
x
v
i
)
ln(\frac{1}{1-x^{v_i}})
ln(1−xvi1)泰勒展开,既然是对多项式求
l
n
ln
ln,肯定是先求导后积分。
l
n
′
(
1
1
−
x
v
)
=
−
l
n
′
(
1
−
x
v
)
=
−
(
−
v
x
v
−
1
)
⋅
(
1
1
−
x
v
)
=
v
∑
i
=
0
∞
x
v
(
i
+
1
)
−
1
=
∑
i
=
1
∞
v
x
v
i
−
1
ln'(\frac{1}{1-x^{v}})=-ln'(1-x^v)=-(-vx^{v-1})\cdot(\frac{1}{1-x^v})=v\sum_{i= 0}^{\infty}x^{v(i+1)-1}=\sum_{i= 1}^{\infty}vx^{vi-1}
ln′(1−xv1)=−ln′(1−xv)=−(−vxv−1)⋅(1−xv1)=v∑i=0∞xv(i+1)−1=∑i=1∞vxvi−1
积分回去之后发现是
∫
l
n
′
(
1
1
−
x
v
)
=
∑
i
=
1
∞
x
v
i
i
\int ln'(\frac{1}{1-x^{v}})= \sum_{i= 1}^{\infty}\frac{x^{vi}}{i}
∫ln′(1−xv1)=∑i=1∞ixvi
非常漂亮的一个式子。
注意到我们仅仅需要考虑
m
m
m以内的
x
x
x
而上面的式子可以采用调和级数求和。
于是我们只需要在
O
(
m
l
o
g
m
)
O(mlogm)
O(mlogm)的时间内就可以求出
l
n
(
A
n
s
(
x
)
)
ln(Ans(x))
ln(Ans(x))
然后多项式exp即可。
多项式exp
还是一样的分治思想
f
(
x
)
=
e
A
(
x
)
f(x)=e^{A(x)}
f(x)=eA(x)
l
n
(
f
(
x
)
)
−
A
(
x
)
=
0
ln(f(x))-A(x)=0
ln(f(x))−A(x)=0
令
g
(
f
(
x
)
)
=
l
n
(
f
(
x
)
)
−
A
(
x
)
g(f(x))=ln(f(x))-A(x)
g(f(x))=ln(f(x))−A(x)
假设我们已经求了
f
0
(
x
)
≡
e
A
(
x
)
(
m
o
d
  
x
n
)
f_0(x)\equiv e^{A(x)}(\mod x^{n})
f0(x)≡eA(x)(modxn)
希望求
f
(
x
)
≡
e
A
(
x
)
(
m
o
d
  
x
2
n
)
f(x)\equiv e^{A(x)}(\mod x^{2n})
f(x)≡eA(x)(modx2n)
那么
g
(
f
(
x
)
)
≡
0
(
m
o
d
  
x
2
n
)
g(f(x))\equiv0(\mod x^{2n})
g(f(x))≡0(modx2n)
考虑在
f
0
f_0
f0处泰勒展开
g
(
f
(
x
)
)
≡
g
(
f
0
(
x
)
)
+
g
′
(
f
0
(
x
)
)
(
f
(
x
)
−
f
0
(
x
)
)
+
g
′
′
(
f
(
x
)
)
2
(
f
(
x
)
−
f
0
(
x
)
)
2
⋯
(
m
o
d
  
x
2
n
)
g(f(x))\equiv g(f_0(x)) + g'(f_0(x))(f(x)-f_0(x))+\frac{g''(f(x))}{2}(f(x)-f_0(x))^2 \cdots(\mod x^{2n})
g(f(x))≡g(f0(x))+g′(f0(x))(f(x)−f0(x))+2g′′(f(x))(f(x)−f0(x))2⋯(modx2n)
注意到
f
(
x
)
≡
f
0
(
x
)
(
m
o
d
  
x
n
)
f(x)\equiv f_0(x)(\mod x^n)
f(x)≡f0(x)(modxn)
所以
f
(
x
)
−
f
0
(
x
)
≡
0
(
m
o
d
  
x
n
)
f(x)-f_0(x)\equiv 0(\mod x^n)
f(x)−f0(x)≡0(modxn)
这就意味着,
f
(
x
)
−
f
(
x
0
)
f(x)-f(x_0)
f(x)−f(x0)在
m
o
d
  
x
2
n
\mod x^{2n}
modx2n意义下的最低幂次不小于
x
n
x^n
xn
所以平方之后的最低幂次不小于
x
2
n
x^{2n}
x2n,在
m
o
d
  
x
2
n
\mod x^{2n}
modx2n意义下为
0
0
0
所以
g
(
f
(
x
)
)
≡
g
(
f
0
(
x
)
)
+
g
′
(
f
0
(
x
)
)
(
f
(
x
)
−
f
0
(
x
)
)
(
m
o
d
  
x
2
n
)
≡
0
g(f(x))\equiv g(f_0(x)) + g'(f_0(x))(f(x)-f_0(x))(\mod x^{2n})\equiv 0
g(f(x))≡g(f0(x))+g′(f0(x))(f(x)−f0(x))(modx2n)≡0
f
(
x
)
≡
f
0
(
x
)
−
g
(
f
0
(
x
)
)
g
′
(
f
0
(
x
)
)
(
m
o
d
  
x
2
n
)
f(x)\equiv f_0(x)-\frac{g(f_0(x))}{g'(f_0(x))}(\mod x^{2n})
f(x)≡f0(x)−g′(f0(x))g(f0(x))(modx2n)
g
′
(
f
0
(
x
)
)
=
1
f
0
(
x
)
g'(f_0(x))=\frac{1}{f_0(x)}
g′(f0(x))=f0(x)1 代入
f
(
x
)
≡
f
0
(
x
)
(
1
−
l
n
(
f
0
(
x
)
)
+
A
(
x
)
)
(
m
o
d
  
x
2
n
)
f(x)\equiv f_0(x)(1-ln(f_0(x))+A(x))(\mod x^{2n})
f(x)≡f0(x)(1−ln(f0(x))+A(x))(modx2n)
分治+多项式求ln+NTT即可。
复杂度
T
(
n
)
=
T
(
n
2
)
+
O
(
n
l
o
g
n
)
=
T
(
n
l
o
g
n
)
T(n)=T(\frac{n}{2})+O(nlogn)=T(nlogn)
T(n)=T(2n)+O(nlogn)=T(nlogn)
代码
// luogu-judger-enable-o2
#include<bits/stdc++.h>
const int N = 524288, P = 998244353;
int ri() {
char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int L, InvL, R[N], w[N], v[N], a[N], b[N];
int fix(int x) {return (x >> 31 & P) + x;}
int add(int a, int b) {return a += b, a >= P ? a - P : a;}
int mul(int a, int b) {return 1LL * a * b % P;}
int Pow(int x, int k) {
int r = 1;
for(;k; x = mul(x, x), k >>= 1)
if(k & 1)
r = mul(r, x);
return r;
}
int Inv(int x) {return Pow(x, P - 2);}
void Pre(int m) {
int x = 0; L = 1;
for(;(L <<= 1) < m; ++x) ;
for(int i = 1;i < L; ++i)
R[i] = R[i >> 1] >> 1 | (i & 1) << x;
int wn = Pow(3, (P - 1) / L); w[0] = 1;
for(int i = 1;i < L; ++i)
w[i] = mul(w[i - 1], wn);
InvL = Inv(L);
}
void DFT(int *F) {
for(int i = 0;i < L; ++i)
if(i < R[i])
std::swap(F[i], F[R[i]]);
for(int i = 1, d = L >> 1; i < L; i <<= 1, d >>= 1)
for(int j = 0;j < L; j += i << 1) {
int *l = F + j, *r = F + j + i, *p = w, tp;
for(int k = i;k--; ++l, ++r, p += d)
tp = mul(*r, *p), *r = fix(*l - tp), *l = add(*l, tp);
}
}
void Inv(const int A[], int *B, int n) {
static int C[N], D[N];
B[0] = Inv(A[0]); int m = 2;
for(; m >> 1 < n; m <<= 1) {
Pre(m << 1);
for(int i = 0;i < m; ++i)
C[i] = A[i], C[i + m] = 0;
for(int i = 0;i < m >> 1; ++i)
D[i] = B[i];
for(int i = m >> 1;i < m << 1; ++i)
D[i] = 0;
DFT(C); DFT(D);
for(int i = 0;i < L; ++i)
C[i] = mul(fix(2 - mul(C[i], D[i])), D[i]);
DFT(C);
for(int i = 0;i < m; ++i)
B[i] = mul(C[L - i & L - 1], InvL);
}
}
void Mul(int *A, int *B, int *C, int m) {
Pre(m << 1);
DFT(A); DFT(B);
for(int i = 0;i < L; ++i)
C[i] = mul(A[i], B[i]);
DFT(C);
}
void Deri(int *A, int *B, int m) {
for(int i = 0;i < m - 1; ++i)
B[i] = mul(A[i + 1], i + 1);
B[m] = 0;
}
void Inte(int *A, int m) {
for(int i = m - 1;i; --i)
A[i] = mul(A[i - 1], Inv(i));
A[0] = 0;
}
void Ln(int *A, int m) {
static int dA[N], G[N];
Deri(A, dA, m);
Inv(A, G, m);
Mul(dA, G, dA, m);
for(int i = 0;i < m; ++i)
G[i] = mul(dA[L - i & L - 1], InvL);
Inte(G, m);
for(int i = 0;i < m; ++i)
A[i] = G[i];
}
void Exp(int *A, int *B, int n) {
static int C[N], D[N];
B[0] = 1; int m = 2;
for(;m >> 1 <= n; m <<= 1) {
for(int i = 0;i < m >> 1; ++i)
C[i] = D[i] = B[i];
for(int i = m >> 1; i < m << 1; ++i)
C[i] = D[i] = 0;
Ln(C, m);
for(int i = 0;i < m; ++i)
C[i] = fix(A[i] - C[i]);
C[0] = add(C[0], 1);
Mul(C, D, C, m);
for(int i = 0;i < m; ++i)
B[i] = mul(C[L - i & L - 1], InvL);
//for(int i = 0;i < m; ++i)
// printf("%d ", B[i]); puts("");
}
}
int main() {
int n = ri(), m = ri();
for(int i = 1;i <= n; ++i)
++v[ri()];
for(int i = 1;i <= m; ++i)
if(v[i])
for(int j = i;j <= m; j += i)
a[j] = add(a[j], mul(v[i], Inv(j / i)));
Exp(a, b, m);
for(int i = 1;i <= m; ++i)
printf("%d\n", b[i]);
return 0;
}