牛客国庆集训派对Day4 F - NTT

版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82989132

题目链接:点击这里

解题思路:

f(x)的i阶导可以写为:

                                                                 \large f^{(i)}=\sum_{j=i}^{n-1}a_{j}*\frac{j!}{(j-i)!}

那么总的式子就是:

                              \large g=\sum_{i=0}^{n-1}(\sum_{j=i}^{n-1}a_{j}*\frac{j!}{(j-i)!}*\sum_{k=n-i-1}^{n-1}a_k*\frac{k!}{(k-n+i+1)!})

变换f(x)第i此导,使得式子对应第j位对应x的j次方的系数:

                                                           \large f^{(i)}(x)=\sum_{j=0}^{n-1}a_{i+j}*\frac{(i+j)!}{j!}

i+j>=n时a[i+j]=0,,没影响.

设F(i)=a[i]*i!。

gd为g(x)的x的d次幂对应的系数是:

                               \large g_d=\sum_{i=0}^{n-1}\sum_{j=0}^{d}F(i+j)*\frac{1}{j!}*F(n-i-1+d-j)*\frac{1}{(d-j)!}

令i=i+j,那么有:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int g = 3; 
const int mod = 998244353;
const int mx = 1<<18;
ll fac[mx],inv[mx],a[mx],b[mx];
int rev[mx],n;
void init()
{
	inv[0] = fac[0] = 1;
	inv[1] = fac[1] = 1;
	for(int i=2;i<mx;i++){
		fac[i] = fac[i-1]*i%mod;
		inv[i] = (mod-mod/i)*inv[mod%i]%mod;
	}
	for(int i=2;i<mx;i++) inv[i] = inv[i]*inv[i-1]%mod;
}
void get_rev(int len)
{
	for(int i=1;i<(1<<len);i++)
	rev[i] = (rev[i>>1]>>1)|((i&1)<<(len-1));
}
ll qpow(ll x,ll y)
{
	ll ans = 1;
	while(y){
		if(y&1) ans = ans*x%mod;
		y >>= 1;
		x = x*x%mod;
	}
	return ans;
}
void ntt(ll *p,int len,int v)
{
	for(int i=0;i<len;i++)
	if(i<rev[i]) swap(p[i],p[rev[i]]);
	for(int i=1;i<len;i<<=1){
		ll tep = qpow(g,(mod-1)/(2*i));
		if(v<0) tep = qpow(tep,mod-2);
		for(int j=0;j<len;j+=(i<<1)){
			ll mul = 1;
			for(int k=j;k<i+j;k++){
				ll x = p[k];
				ll y = mul*p[k+i]%mod;
				p[k] = (x + y)%mod;
				p[k+i] = (x - y + mod)%mod;
				mul = mul*tep%mod;
			}
		}
	}
	if(v==-1){
		ll invs = qpow(len,mod-2);
		for(int i=0;i<len;i++) p[i] = p[i]*invs%mod;
	}
}
int main()
{
	init();
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lld",a+i);
		a[i] = a[i]*fac[i]%mod; 
		b[i] = inv[i];
	}
	int len = 1;
	while((1<<len)<2*n) len++;
	get_rev(len);
	len = 1<<len;
	ntt(a,len,1);ntt(b,len,1);
	for(int i=0;i<len;i++) a[i] = a[i]*a[i]%mod;
	for(int i=0;i<len;i++) b[i] = b[i]*b[i]%mod;
	ntt(a,len,-1);ntt(b,len,-1);
	for(int i=0;i<n;i++)
	printf("%lld%c",a[i+n-1]*b[i]%mod,i==n-1?'\n':' ');
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/82989132