HDU 6061

来源:互联网 发布:泛普软件怎么样 编辑:程序博客网 时间:2024/05/18 02:28

原题连接:
http://acm.hdu.edu.cn/showproblem.php?pid=6061

题目的意思可以理解为

给定多项式:

g(x)=i=0ncixi

计算多项式g(xs)

推导:

g(xs)=i=0nci(xs)i=i=0nk=0i(ci(ik)xk(s)ik)=k=0ni=kn(ci(ik)xk(s)ik)=k=0nxki=kn(ci(ik)(s)ik)=k=0nxkk!i=kn(cii!(ik)!(s)ik)

令:

bk=cnk(nk)!

对于:

i=kn(cii!(ik)!(s)ik)=i=kn((s)ik(ik)!bni)

因为:ni+ik=nk

h=nk

ah=i=0h((s)ii!bhi)

可以快速计算a[]

从而得到新函数的系数形式。

#include <queue>#include <string.h>#include <stdio.h>#include <algorithm>#include <math.h>#define MAXN 400005using 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;}
原创粉丝点击