COGS 2189. [HZOI 2015] 帕秋莉的超级多项式(牛顿迭代)

传送门

题意:
求:

G(x)=(1+ln(1+1exp(1F(x))))k

题解:

依次进行牛顿迭代即可。

注意多项式 k 次方不需要快速幂:

lnG(x)=ln(F(x)k)=klnF(x)

多项式再 exp 即可。

#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
inline int rd() {
    char ch=getchar(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
    return i*f;
}
inline void W(int x){
    static int buf[50];
    if(!x) {putchar('0'); return;}
    if(x<0) {putchar('-');x=-x;}
    while(x) {buf[++buf[0]]=x%10; x/=10;}
    while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}
const int N=1e5+50;
const int mod=998244353;
const int G=3;
const int inv2=499122177;
inline int power(int a,int b) {
    int rs=1;
    for(;b;b>>=1,a=(LL)a*a%mod) if(b&1) rs=(LL)rs*a%mod;
    return rs;
}
int n,p,inv[N*8];
int k,f[N*8],g[N*8],ig[N*8],ep[N*8],lp[N*8],ip[N*8],rp[N*8],rp2[N*8],w[N*8],pos[N*8];
inline void init() {
    for(int i=1;i<k;i++) pos[i]=(i&1)?((pos[i>>1]>>1)^(k>>1)):(pos[i>>1]>>1);
}
inline void dft(int *a,int o=1) {
    for(int i=1;i<k;i++) (pos[i]>i)&&(swap(a[pos[i]],a[i]),0);
    for(int bl=1;bl<k;bl<<=1){
        int tl=bl<<1,wn=power(G,(mod-1)/tl); w[0]=1;
        for(int i=1;i<bl;i++) w[i]=(LL)w[i-1]*wn%mod;
        for(int bg=0;bg<k;bg+=tl)
            for(int j=0;j<bl;j++){
                int &t1=a[bg+j],&t2=a[bg+j+bl],t3=(LL)t2*w[j]%mod;
                t2=(t1-t3<0?t1-t3+mod:t1-t3);
                t1=(t1+t3>=mod?t1+t3-mod:t1+t3);
            }
    }
    if(o!=1) {
        const int inv=power(k,mod-2);
        for(int i=0;i<k;i++) a[i]=(LL)a[i]*inv%mod;
    }
}
inline void calc_inverse(int *a,int *b,int len) {
    if(len==1) {b[0]=power(a[0],mod-2); return;}
    if(len!=1) calc_inverse(a,b,len>>1); 
    k=len<<1; init();
    for(int i=0;i<len;i++) ip[i]=a[i];
    for(int i=len;i<k;i++) ip[i]=0;
    for(int i=(len>>1);i<k;i++) b[i]=0;
    dft(b); dft(ip);
    for(int i=0;i<k;i++) b[i]=(mod+2ll*b[i]-(LL)b[i]*b[i]%mod*ip[i]%mod)%mod;
    dft(b,-1); reverse(b+1,b+k);
    for(int i=len;i<k;i++) b[i]=0;
}
inline void calc_ln(int *a,int *b,int len) {
    calc_inverse(a,lp,len); 
    k=len<<1; init();
    for(int i=0;i<len-1;i++) b[i]=(LL)a[i+1]*(i+1)%mod;
    for(int i=len-1;i<k;i++) b[i]=0;
    dft(lp); dft(b);
    for(int i=0;i<k;i++) b[i]=(LL)b[i]*lp[i]%mod;
    dft(b,-1); reverse(b+1,b+k);
    for(int i=len-1;i>=1;i--) b[i]=(LL)b[i-1]*inv[i]%mod;
    for(int i=len;i<k;i++) b[i]=0;
    b[0]=0; return;
}
inline void calc_exp(int *a,int *b,int len) {
    if(len==1) {b[0]=1; return;}
    if(len!=1) calc_exp(a,b,len>>1);
    calc_ln(b,ep,len);
    k=len<<1; init();
    for(int i=0;i<len;i++) ep[i]=(mod-ep[i]+a[i])%mod;
    ep[0]++;
    for(int i=len;i<k;i++) ep[i]=(b[i]=0);
    dft(ep); dft(b);
    for(int i=0;i<k;i++) b[i]=(LL)b[i]*ep[i]%mod;
    dft(b,-1); reverse(b+1,b+k);
    for(int i=len;i<k;i++) b[i]=0;
}
inline void calc_root(int *a,int *b,int len) {
    if(len==1) {b[0]=sqrt(a[0]); return;}
    if(len!=1) calc_root(a,b,len>>1);
    calc_inverse(b,rp,len);
    k=len<<1; init();
    for(int i=0;i<len;i++) rp2[i]=a[i];
    for(int i=len;i<k;i++) rp2[i]=0;
    dft(rp); dft(rp2);
    for(int i=0;i<k;i++) rp[i]=(LL)rp[i]*rp2[i]%mod;
    dft(rp,-1); reverse(rp+1,rp+k);
    for(int i=0;i<len;i++) b[i]=((LL)b[i]*inv2%mod+(LL)rp[i]*inv2%mod)%mod;
    for(int i=len;i<k;i++) b[i]=0;
}
int main() {
    n=rd(), p=rd(); inv[1]=1;
    for(int i=2;i<n;i++) inv[i]=(mod-(LL)mod/i*inv[mod%i]%mod)%mod;
    for(int i=0;i<n;i++) f[i]=rd();
    int len=1; for(;len<n;len<<=1);
    calc_root(f,g,len);
    calc_inverse(g,ig,len);
    for(int i=1;i<n;i++) f[i]=(LL)ig[i-1]*inv[i]%mod;
    f[0]=0;
    calc_exp(f,g,len);
    calc_inverse(g,ig,len);
    for(int i=0;i<n;i++) f[i]=ig[i];
    f[0]++; calc_ln(f,g,len);
    g[0]++; calc_ln(g,ig,len);
    for(int i=0;i<n;i++) ig[i]=(LL)ig[i]*p%mod;
    calc_exp(ig,f,len);
    for(int i=0;i<n-1;i++) f[i]=(LL)f[i+1]*(i+1)%mod;
    for(int i=0;i<n-1;i++) W(f[i]),putchar(' ');
    W(0); putchar('\n');
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值