原题连接:
http://acm.hdu.edu.cn/showproblem.php?pid=6061
题目的意思可以理解为
给定多项式:
g(x)=∑i=0ncixi
计算多项式 g(x−s)
推导:
g(x−s)=∑i=0nci(x−s)i=∑i=0n∑k=0i(ci(ik)xk(−s)i−k)=∑k=0n∑i=kn(ci(ik)xk(−s)i−k)=∑k=0nxk∑i=kn(ci(ik)(−s)i−k)=∑k=0nxkk!∑i=kn(cii!(i−k)!(−s)i−k)
令:
bk=cn−k∗(n−k)!
对于:
∑i=kn(cii!(i−k)!(−s)i−k)=∑i=kn((−s)i−k(i−k)!∗bn−i)
因为: n−i+i−k=n−k
令 h=n−k :
ah=∑i=0h((−s)ii!∗bh−i)
可以快速计算a[]
从而得到新函数的系数形式。
#include <queue>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#define MAXN 400005
using namespace std;
typedef long long LL;
const LL P=998244353;
const LL G=3;
LL Pow(LL a,int b)
{
LL tmp=1;
while(b)
{
if(b&1)
tmp=tmp*a%P;
a=a*a%P;
b>>=1;
}
return tmp;
}
void change(LL y[],int n)
{
int b=n>>1,s=n-1;
for(int i=1,j=n>>1;i<s;i++)
{
if(i<j)swap(y[i],y[j]);
int k=b;
while(j>=k)
{
j-=k;
k>>=1;
}
j+=k;
}
}
void NTT_(LL y[],int len,int on)
{
change(y,len);
for(int h=2;h<=len;h<<=1)
{
LL wh=Pow(G,(P-1)/h);
if(on<0)wh=Pow(wh,P-2);
for(int i=0;i<len;i+=h)
{
LL w=1;
int r=h>>1;
for(int k=i,s=r+i;k<s;k++)
{
LL u=y[k];
LL t=w*y[k+r]%P;
y[k]=u+t; if(y[k]>=P)y[k]-=P;
y[k+r]=u-t; if(y[k+r]<0) y[k+r]+=P;
w=w*wh%P;
}
}
}
if(on<0)
{
LL I=Pow((LL)len,P-2);
for(int i=0;i<len;i++) y[i]=y[i]*I%P;
}
}
LL c[MAXN];
LL b[MAXN];
LL fac[MAXN];
LL Ivn[MAXN];
int main ()
{
Ivn[0]=Ivn[1]=1;
fac[0]=1;
for(int i=1;i<MAXN;i++) fac[i]=fac[i-1]*i%P;
for(int i=2;i<MAXN;i++) Ivn[i]=Pow(fac[i],P-2);
int n;
while(scanf("%d",&n)!=EOF)
{
n++;
for(int i=0;i<n;i++) scanf("%lld",c+i);
for(int i=0;i<n;i++) b[i]=c[n-i-1]*fac[n-i-1]%P;
int m;
LL S=0;
int a;
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d",&a);
S+=(LL)a;
if(S>=P)S-=P;
}
for(int i=0 ; i<n ; i++) c[i]=Pow(P-S,i)*Ivn[i]%P;
int len=1;
while(len<(n<<1))len<<=1;
for(int i=n;i<len;i++) c[i]= b[i] = 0;
NTT_(b,len,1);
NTT_(c,len,1);
for(int i=0;i<len;i++) c[i]= c[i] * b[i] % P ;
NTT_(c,len,-1);
for(int i=0;i<n;i++) printf("%lld ",c[n-1-i] * Ivn[i] % P);
printf("\n");
}
return 0;
}