在幻想乡,帕秋莉·诺蕾姬(パチュリー·ノーレッジ)是以宅在图书馆闻名的魔法使。
其语文,数学,英语,物理,化学,生物,政治,历史,地理,哲♂学,无所不通晓。
今天,她在研♂究多项式……
“小恶魔……”,帕秋莉突然召唤道。
“来啦,帕秋莉sama~”,小恶魔高兴地飘到了帕秋莉的身边。
帕秋莉头也不抬地将一张写满公式的纸递给了小恶魔,
“帮我把这个式子求出来。”
“唔……”,小恶魔对帕秋莉冷淡的态度有些失望,
不过,先以公事为先吧,以后,哼哼,再把帕秋莉攻略掉!
小恶魔看了看帕秋莉给她的公式:
第一行:两个数n,k
第二行:n个数:零次项到n-1次项的系数
n个数,分别表示结果的零次项到n-1次项的系数
10 850364419
2809 194360192 321022656 126565118 52396030 592803840 203610880 479432704 687895263 119537663
547604268 801849496 580773243 716155766 229972082 99551288 331271101 407139181 121537791 0
数据范围:
1<=n<=100000
0<=k<=1000000000
0<=F(x)的各项系数<998244353
by stdafx && 神利·代目
除了题目描述以外十分丧心病狂的一道NTT板子题.jpg
练手还是可以的……但正式比赛这种毒瘤东西还是不要出现的好……
思路:
直接按题意模拟啊喂……
具体怎么模拟详见这里
#include
using namespace std;
typedef long long ll;
const int N=100009*3;
const ll md=998244353;
const int inv2=499122177;
int n,m,k,rev[N];
int f[N],g[N],inv[N];
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0' || '9'while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
return x;
}
inline void write(int x){if(x>=10)write(x/10);putchar(x%10+'0');}
inline int add(int a,int b){a+=b;if(a>=md)return a-md;return a;}
inline int mul(int a,int b){return (ll)a*b%md;}
inline int qpow(int a,int b)
{
int ret=1;
while(b)
{
if(b&1)
ret=mul(ret,a);
a=mul(a,a);
b>>=1;
}
return ret;
}
void initinv()
{
inv[1]=1;
for(int i=2;iinline void initrev(int n)
{
for(int i=0;i>1]>>1)|((i&1)*(n>>1));
}
inline void NTT(int *a,int n,bool f)
{
for(int i=0;iif(ifor(int h=2;h<=n;h<<=1)
{
int w=qpow(3,(md-1)/h);
if(f)w=qpow(w,md-2);
for(int j=0;jint wn=1;
for(int k=j;k>1);k++)
{
int x=a[k],y=mul(wn,a[k+(h>>1)]);
a[k]=add(x,y);
a[k+(h>>1)]=add(x-y,md);
wn=mul(wn,w);
}
}
}
if(f)
for(int i=0,invn=inv[n];iinline void cinv(int *a,int *b,int n)
{
static int C[N];
if(n==0)
{
b[0]=qpow(a[0],md-2);
return;
}
cinv(a,b,n>>1);
memcpy(C,a,sizeof(a[0])*n);
memset(C+n,0,sizeof(a[0])*n);
n<<=1;initrev(n);
for(int i=0;i>1]>>1)|((i&1)*(n>>1));
NTT(C,n,0);NTT(b,n,0);
for(int i=0;i2,b[i])-mul(C[i],mul(b[i],b[i])),md);
NTT(b,n,1);n>>=1;
memset(b+n,0,sizeof(b[0])*n);
}
inline void cln(int *f,int *g,int n)
{
static int D[N],A[N],m;
memset(D,0,sizeof(D));
memset(A,0,sizeof(A));
for(int i=0;i1],(i+1));
D[n]=0;
for(m=1;m<=n;m<<=1);
cinv(f,A,n);initrev(m);
NTT(A,m,0);NTT(D,m,0);
for(int i=0;i1);
for(int i=1;i<=n;i++)
g[i]=mul(A[i-1],inv[i]);
g[0]=0;
}
inline void cintegrate(int *f,int n)
{
for(int i=n;i>=1;i--)
f[i]=mul(f[i-1],inv[i]);
f[0]=0;
}
inline void cderivation(int *f,int n)
{
for(int i=1;i1]=mul(f[i],i);
f[n-1]=0;
}
inline void cexp(int *a,int *b,int n)
{
static int D[N];
if(n==1)
{
b[0]=1;
return;
}
cexp(a,b,n>>1);
memset(D,0,sizeof(D));
cln(b,D,n);
for(int i=0;i0]=add(1,D[0]);
n<<=1;initrev(n);
NTT(D,n,0);NTT(b,n,0);
for(int i=0;i1);n>>=1;
memset(b+n,0,sizeof(b[0])*n);
}
void csqrt(int *a,int *b,int n)
{
static int C[N],D[N];
if(n==1)
{
b[0]=sqrt(a[0]);
return;
}
csqrt(a,b,n>>1);
memset(D,0,sizeof(D));
cinv(b,D,n);
memcpy(C,a,sizeof(a[0])*n);
memset(C+n,0,sizeof(C[0])*n);
n<<=1;NTT(C,n,0);NTT(b,n,0);NTT(D,n,0);
for(int i=0;i1);n>>=1;
memset(b+n,0,sizeof(b[0])*n);
}
inline void cpow(int *f,int *g,int n,int k)
{
static int C[N];
memset(C,0,sizeof(C));
cln(f,C,m);
for(int i=0;iint main()
{
freopen("polynomial.in","r",stdin);
freopen("polynomial.out","w",stdout);
initinv();
n=read();k=read();
for(int i=0;ifor(m=1;m<=n;m<<=1);
csqrt(f,g,m);
memset(f,0,sizeof(f));
cinv(g,f,m);
cintegrate(f,n);
memset(g,0,sizeof(g));
cexp(f,g,m);
memset(f,0,sizeof(f));
cinv(g,f,m);
f[0]=add(f[0],1);
memset(g,0,sizeof(g));
cln(f,g,m);
g[0]=add(g[0],1);
memset(f,0,sizeof(f));
cpow(g,f,m,k);
cderivation(f,n);
for(int i=0;iputchar(' ');
puts("");
return 0;
}