题目
题目描述
给定一个 n-1n−1 次多项式 A(x)A(x),求一个在 \bmod\ x^nmod x
n
意义下的多项式 B(x)B(x),使得 B(x) \equiv A^k(x) \ (\bmod\ x^n)B(x)≡A
k
(x) (mod x
n
)。
多项式的系数在 \bmod\ 998244353mod 998244353 的意义下进行运算。
输入格式
第一行两个正整数 n,kn,k。
接下来 nn 个整数,依次表示多项式的系数 a_0, a_1, \dots, a_{n-1}a
0
,a
1
,…,a
n−1
。
保证 a_0 = 1a
0
=1。
输出格式
输出 nn 个整数,表示答案多项式的系数 b_0, b_1, \dots, b_{n-1}b
0
,b
1
,…,b
n−1
。
输入输出样例
输入 #1复制
9 18948465
1 2 3 4 5 6 7 8 9
输出 #1复制
1 37896930 597086012 720637306 161940419 360472177 560327751 446560856 524295016
输入 #2复制
4 1
1 1 0 0
输出 #2复制
1 1 0 0
输入 #3复制
4 2
1 1 0 0
输出 #3复制
1 2 1 0
输入 #4复制
4 3
1 1 0 0
输出 #4复制
1 3 3 1
说明/提示
对于 100%100% 的数据:1 < n \leq 10^51<n≤10
5
,2 \leq k \leq 10{105}2≤k≤10
10
5
,a_i \in [0,998244352] \cap \mathbb{Z}a
i
∈[0,998244352]∩Z。
思路
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 400003,mod = 998244353,G = 3,Gi = 332748118;
int n,k,A[N];
int power(int a,int b){
int res = 1;
while(b){
if(b & 1) res = (LL) res * a % mod;
a = (LL) a * a % mod;
b >>= 1;
}
return res;
}
int rev[N];
void NTT(int *A,int limit,int type){
for(i = 0;i < limit;i ++)
if(i < rev[i]) swap(A[i],A[rev[i]]);
for(mid = 1;mid < limit;mid <<= 1){
int Wn = power(type == 1 ? G : Gi,(mod - 1) / (mid << 1));
for(j = 0;j < limit;j += mid << 1){
int w = 1;
for(k = 0;k < mid;k ++,w = (LL) w * Wn % mod){
int x = A[j + k],y = (LL) w * A[j + k + mid] % mod;
A[j + k] = (x + y) % mod;
A[j + k + mid] = (x - y + mod) % mod;
}
}
}
if(type == -1){
int inv = power(limit,mod - 2);
for(i = 0;i < limit;i ++) A[i] = (LL) A[i] * inv % mod;
}
}
int ans[N];
void poly_inv(int *A,int deg){
int tmp[N];
if(deg == 1){
ans[0] = power(A[0],mod - 2);
return;
}
poly_inv(A,deg + 1 >> 1);
int limit = 1,L = -1;
while(limit <= (deg << 1)){limit <<= 1; L ++;}
for(i = 0;i < limit;i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << L);
for(i = 0;i < deg;i ++) tmp[i] = A[i];
for(i = deg;i < limit;i ++) tmp[i] = 0;
NTT(tmp,limit,1); NTT(ans,limit,1);
for(i = 0;i < limit;i ++) ans[i] = (2 - (LL) ans[i] * tmp[i] % mod + mod) % mod * ans[i] % mod;
NTT(ans,limit,-1);
for(i = deg;i < limit;i ++) ans[i] = 0;
}
int Ln[N];
void poly_Ln(int *A,int deg){
int tmp[N];
poly_inv(A,deg);
for(i = 1;i < deg;i ++) tmp[i - 1] = (LL) i * A[i] % mod;
tmp[deg - 1] = 0;
int limit = 1,L = -1;
while(limit <= (deg << 1)){limit <<= 1; L ++;}
for(i = 0;i < limit;i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << L);
NTT(ans,limit,1); NTT(tmp,limit,1);
for(i = 0;i < limit;i ++) Ln[i] = (LL) ans[i] * tmp[i] % mod;
NTT(Ln,limit,-1);
for(i = deg + 1;i < limit;i ++) Ln[i] = 0;
for(i = deg;i;i --) Ln[i] = (LL) Ln[i - 1] * power(i,mod - 2) % mod;
Ln[0] = 0;
for(i = 0;i < limit;i ++) ans[i] = tmp[i] = 0;
}
int Exp[N];
void poly_Exp(int *A,int deg){
if(deg == 1){
Exp[0] = 1;
return;
}
poly_Exp(A,deg + 1 >> 1);
poly_Ln(Exp,deg);
for(i = 0;i < deg;i ++) Ln[i] = (A[i] + (i == 0) - Ln[i] + mod) % mod;
int limit = 1,L = -1;
while(limit <= (deg << 1)){limit <<= 1; L ++;}
for(i = 0;i < limit;i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << L);
NTT(Exp,limit,1); NTT(Ln,limit,1);
for(i = 0;i < limit;i ++) Exp[i] = (LL) Exp[i] * Ln[i] % mod;
NTT(Exp,limit,-1);
for(i = deg;i < limit;i ++) Exp[i] = 0;
for(i = 0;i < limit;i ++) Ln[i] = ans[i] = 0;
}
int main()
{
n = read(); k = read();
for(i = 0;i < n;i ++) A[i] = read();
poly_Ln(A,n);
for(i = 0;i < n;i ++) A[i] = (LL) Ln[i] * k % mod,Ln[i] = 0;
poly_Exp(A,n);
for(i = 0;i < n;i ++) printf("%d ",Exp[i]);
}