p5349 幂

分析

https://www.cnblogs.com/cjyyb/p/10822490.html

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int g = 3;
const int N = 2e5;
const int G = 332748118;
const int mod = 998244353;
int f[400100],a[400100],b[400100],fac[400100],inv[400100],val,A[400100],R,r[400100];
inline int pw(int x,int p){int res=1;while(p){if(p&1)res=res*x%mod;x=x*x%mod;p>>=1;}return res;}
inline void ntt(int a[],int opt,int n){
    int i,j,k,inv=pw(n,mod-2),now,wn,w,p,q;
    for(i=0;i<n;i++)if(i<r[i])swap(a[i],a[r[i]]);
    for(i=1;i<n;i<<=1){
      now=(opt==1?g:G),wn=pw(now,(mod-1)/(i<<1));
      for(j=0;j<n;j+=(i<<1))
        for(k=0,w=1;k<i;k++,w=w*wn%mod)
          p=a[j+k],q=a[i+j+k]*w%mod,a[j+k]=(p+q)%mod,a[i+j+k]=(p-q+mod)%mod;
    }
    if(opt==-1)for(i=0;i<n;i++)a[i]=a[i]*inv%mod;
}
inline void go_to_work(int le,int ri){
    if(le==ri)return;
    int i,j,k,n,m=ri-le,len=0,mid=(le+ri)>>1;
    go_to_work(le,mid);for(n=1;n<=(m+1)*2;n<<=1)len++;
    for(i=0;i<n;i++)r[i]=((r[i>>1]>>1)|((i&1)<<(len-1)));
    for(i=0;i<n;i++)a[i]=b[i]=0;for(i=0;i<=mid-le;i++)a[i]=f[i+le];
    for(i=0;i<=m;i++)b[i]=val*inv[i]%mod;ntt(a,1,n),ntt(b,1,n);
    for(i=0;i<n;i++)a[i]=a[i]*b[i]%mod;ntt(a,-1,n);
    for(i=mid+1;i<=ri;i++)f[i]=(f[i]+a[i-le])%mod;
    go_to_work(mid+1,ri);return;
    
}
signed main(){
    int n,i,j,k,Ans=0;
    scanf("%lld%lld",&n,&R);
    f[0]=pw((1-R+mod)%mod,mod-2);
    for(i=0;i<=n;i++)scanf("%lld",&A[i]);
    fac[0]=1;for(i=1;i<=N;i++)fac[i]=fac[i-1]*i%mod;
    inv[N]=pw(fac[N],mod-2);for(i=N-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
    val=R*pw((1-R+mod)%mod,mod-2)%mod;go_to_work(0,n);
    for(i=0;i<=n;i++)Ans=(Ans+f[i]*A[i]%mod*fac[i]%mod)%mod;
    printf("%lld\n",Ans);return 0;
}

 

posted @ 2019-10-14 07:14  水题收割者  阅读(122)  评论(0编辑  收藏  举报