[COGS2189][HZOI 2015]帕秋莉的超级多项式-NTT-多项式求逆-多项式求ln-多项式开方-多项式求exp-多项式快速幂

帕秋莉的超级多项式

【题目描述】

在幻想乡,帕秋莉·诺蕾姬(パチュリー·ノーレッジ)是以宅在图书馆闻名的魔法使。
其语文,数学,英语,物理,化学,生物,政治,历史,地理,哲♂学,无所不通晓。

今天,她在研♂究多项式……
“小恶魔……”,帕秋莉突然召唤道。
“来啦,帕秋莉sama~”,小恶魔高兴地飘到了帕秋莉的身边。
帕秋莉头也不抬地将一张写满公式的纸递给了小恶魔,
“帮我把这个式子求出来。”
“唔……”,小恶魔对帕秋莉冷淡的态度有些失望,
不过,先以公事为先吧,以后,哼哼,再把帕秋莉攻略掉!
小恶魔看了看帕秋莉给她的公式:

G(x)=(1+ln(1+1exp(1F(x))))k G ( x ) = ( 1 + ln ⁡ ( 1 + 1 e x p ( ∫ 1 F ( x ) ) ) ) k

(+﹏+)~
这是啥。。。
不过小恶魔是很聪明的,瞬间学会了C++,编好了程序
当她兴高采烈地去找帕秋莉时,帕秋莉用很疑惑的眼神看着她
“怎么啦?”小恶魔问道,
“F(x)是个多项式哦。”
“啥!!Σ( ° △ °|||)︴”,不会了……
就这样,小恶魔找到了你
帮帮小恶魔吧!
题目概述:
给定n,k,F(x),其中F(x)是常数项为完全平方数的多项式,其最高次项为n-1,一切运算都在mod x^n的意义下进行,积分之后默认常数项为0,求G’(x),即G(x) mod x^n的导函数。(先mod再求导)
由于答案有可能非常的大,你只需要输出G’(x)每项的系数mod 998244353的余数的非负整数即可。

【输入格式】

第一行:两个数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;
}

你可能感兴趣的:(快速数论变换【NTT】)