描述
题目太**鬼畜了,复制不下来
题目大意:给一个多项式
f(x)
f
(
x
)
fi(x)
f
i
(
x
)
为
f(x)
f
(
x
)
的i阶导数
最后让我们求一个多项式
g(x)
g
(
x
)
g(x)=∑n−1i=0fi(x)∗fn−i−1(x)
g
(
x
)
=
∑
i
=
0
n
−
1
f
i
(
x
)
∗
f
n
−
i
−
1
(
x
)
输入格式
第一行一个正整数 n
第二行 n 个整数,表示a0,a1…an−1
输出格式
假设
g(x)=∑n−1i=0bixi
g
(
x
)
=
∑
i
=
0
n
−
1
b
i
x
i
第一行输出 n 个整数,表示 b0,b1..bn−1 对 998244353 取模的值
样例1
样例输入
3
1 2 3
样例输出
16 48 72
样例2
见下载文件
暴力
n2logn
n
2
l
o
g
n
就不讲了,按照题意做
这种题看一眼头就炸了是吗
(其实这题蛮暴力的,大力推导,代码也好写
我们假设
gi
g
i
为
g(x)
g
(
x
)
中
xi
x
i
的系数
fi
f
i
同理
经过推导我们可以得到
gd=∑n−1i=0∑dj=0fi+j∗(i+j)!j!
g
d
=
∑
i
=
0
n
−
1
∑
j
=
0
d
f
i
+
j
∗
(
i
+
j
)
!
j
!
∗fn−1−i+d−j∗(n−1−i+d−j)!(d−j)!
∗
f
n
−
1
−
i
+
d
−
j
∗
(
n
−
1
−
i
+
d
−
j
)
!
(
d
−
j
)
!
相当于是枚举每一位,原函数中每一阶暴力展开
令
fi=fi∗i!
f
i
=
f
i
∗
i
!
化为
gd=∑i=0n−1∑j=0dfi+j∗1j!∗fn−1−i+d−j∗1(d−j)!
g
d
=
∑
i
=
0
n
−
1
∑
j
=
0
d
f
i
+
j
∗
1
j
!
∗
f
n
−
1
−
i
+
d
−
j
∗
1
(
d
−
j
)
!
大部分项只和
i+j
i
+
j
有关,只有阶乘单单和j有关,这个形式我们又是可以推导成另一个式子
那么我们用
i
i
表示原来的
gd=∑n−1+di=0fi∗fn−1+d−i∗∑dj=01(d−j)!j!∗[j<=i]∗[d−j<=n−1+d−i]
g
d
=
∑
i
=
0
n
−
1
+
d
f
i
∗
f
n
−
1
+
d
−
i
∗
∑
j
=
0
d
1
(
d
−
j
)
!
j
!
∗
[
j
<=
i
]
∗
[
d
−
j
<=
n
−
1
+
d
−
i
]
棘手的是后面的部分
观察发现
若
i<j
i
<
j
(即条件一不满足)
那么
i<d
i
<
d
,
n−1+d−i>=n
n
−
1
+
d
−
i
>=
n
则
fn−1+d−i=0
f
n
−
1
+
d
−
i
=
0
,会被自动过滤
若
d−j>n−1+d−i
d
−
j
>
n
−
1
+
d
−
i
则
i>n−1+j>=n−1
i
>
n
−
1
+
j
>=
n
−
1
则
fi=0
f
i
=
0
,也会被过滤
那现在我们只要求
gd=∑n−1+di=0fi∗fn−1+d−i∗∑dj=01(d−j)!j!
g
d
=
∑
i
=
0
n
−
1
+
d
f
i
∗
f
n
−
1
+
d
−
i
∗
∑
j
=
0
d
1
(
d
−
j
)
!
j
!
了
后面那个求和就等于
2dd!
2
d
d
!
(组合数学)
前面的部分可以用
FFT
F
F
T
解决
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,j,k) for(int i = j;i <= k;++i)
#ifdef M_pi
const double pi = M_pi;
#else
const double pi = acos(-1.0);
#endif
const int g = 3;
int N ;
const int p = 998244353;
const int NUM = 22;
int n;
ll f[300010] , jc[300010];
ll a[300010] , b[300010];
ll ans[300010];
int r[300010];
int flen;
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
ll mul(ll a, ll b){return (ll)(a*b)%p;}
ll power(ll a, ll b)
{
ll ans = 1;
a %= p;
while(b) {
if(b & 1)
ans = ans * a % p,
b--;
b >>= 1;
a = a * a % p;
}
return ans%p;
}
void ntt(ll *a ,int f){
for(int i = 0; i < flen; ++i)
if(i < r[i]) swap(a[i], a[r[i]]);
int cnt = 0;
for(int len = 2;len <= flen;len *= 2){
ll wn = power( g , (p - 1) / len );
if(f == -1) wn = power(wn , p-2);
for(int k = 0;k <= flen / len - 1;++k){
int st = k * len;
ll w = 1;
for(int i = 0;i < len / 2;++i){
ll x = a[st + i] % p,
y = (a[st + i + len / 2] % p) * w % p;
a[st + i] = (x + y + p) % p;
a[st + i + len / 2] = (x - y + p) % p;
w = w * wn % p;
}
}
}
if(f == -1){
int inv = power(N , p-2);
for(int i = 0;i < N ;++i)
a[i] = 1ll * a[i] * inv % p;
}
return;
}
void solve_NTT(int n,int m)
{
flen = 1;
while( flen < (n + m + 1)) flen *= 2;
N = flen;
for(int i = n + 1;i < flen;++i) a[i] = 0;
for(int i = m + 1;i < flen;++i) b[i] = 0;
int l = log2(flen);
for(int i = 0;i < flen;++i){
r[i] = r[i>>1]>>1;
if(i & 1) r[i] |= 1<<(l-1);
}
ntt(a,1);
ntt(b,1);
for(int i = 0;i < flen;++i) a[i] = mul(a[i] , b[i]);
ntt(a,-1);
return;
}
void putout(ll x){
if(x >= 10) putout(x / 10);
putchar(x % 10 + '0');
}
void init()
{
n = read();
rep(i,0,n-1) f[i] = read();
jc[0] = 1;
rep(i,1,n) jc[i] = jc[i-1] * i % p;
rep(i,0,n-1) f[i] = f[i] * jc[i] % p;
rep(i,0,n-1) a[i] = b[i] = f[i];
solve_NTT(n-1,n-1);
ll now = 1;
rep(i,0,n-1) jc[i] = power(jc[i],p-2);
rep(i,0,n-1)
putout(((a[i+n-1] * now)%p * jc[i])%p),
putchar(' '),
now = now * 2 % p;
return;
}
int main()
{
init();
return 0;
}