zoukankan      html  css  js  c++  java
  • Luogu P5349 幂

    大力数学题,发现自己好久没写多项式水平急速下降,求逆都要写挂233

    首先看到关于多项式的等比数列求和,我们容易想到先求出每一项的系数然后最后累加起来即可,即设(f_i=sum_{n=0}^{infty} n^kr^n),那么最后(ans=sum_{i=0}^m a_if_i)

    然后你直接去OEIS就找到了它的生成函数,一波搞定233

    好了我们认真开始推式子,(f_i=sum_{n=0}^{infty} n^kr^n)

    (rcdot f_i=sum_{n=1}^infty (n-1)^kr^n)

    ((1-r)f_i=sum_{n=1}^infty (n^k-(n-1)^k)r^n=rcdot sum_{n=0}^infty ((n+1)^k-n^k)r^n)

    上式等于(rcdot sum_{n=0}^inftysum_{j=0}^{i-1} C_i^jcdot n^i r^n=rcdot sum_{j=0}^{i-1} C_i^jcdot sum_{n=0}^infty n^i r^n=rcdotsum_{j=0}^{i-1} C_i^jcdot f_j)

    即有(f_i=frac{r}{1-r}cdot sum_{j=0}^{i-1} C_i^jcdot f_j)

    把组合数展开就有(frac{f_i}{i!}=sum_{j=0}^{i-1} frac{f_j}{j!}(frac{r}{1-r}cdotfrac{1}{(k-i)!}))

    看出来这是个分治NTT的形式,用类似于板子题的方法转化为多项式求逆解决

    具体地,令(F(x)=1-frac{1}{i!}cdotfrac{r}{1-r}),对(F(x))求逆得出(G(x))再乘回(i!)即可求出(f(x))

    CODE

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=100005,mod=998244353;
    int n,r,F[N<<3],G[N<<3],fact[N],inv[N],A[N],invr,mtir,ans;
    class FileInputOutput
    {
        private:
            static const int S=1<<21;
            #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
            char Fin[S],*A,*B;
        public:
            Tp inline void read(T& x)
            {
                x=0; char ch; while (!isdigit(ch=tc()));
                while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
            }
            #undef tc
    }File;
    inline int sum(CI x,CI y)
    {
        int t=x+y; return t>=mod?t-mod:t;
    }
    inline int sub(CI x,CI y)
    {
        int t=x-y; return t<0?t+mod:t;
    }
    inline int quick_pow(int x,int p=mod-2,int mul=1)
    {
        for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
    }
    inline void init(CI n)
    {
        RI i; for (fact[0]=i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;
        for (inv[n]=quick_pow(fact[n]),i=n-1;~i;--i) inv[i]=1LL*inv[i+1]*(i+1)%mod;
    }
    class Poly_Solver
    {
        private:
            int rev[N<<3],T[N<<3],lim,p;
            inline void init(CI n)
            {
                for (lim=1,p=0;lim<=(n<<1);lim<<=1,++p);
                for (RI i=0;i<lim;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<p-1);
            }
            inline void swap(int& x,int& y)
            {
                int t=x; x=y; y=t;
            }
            inline void NTT(int *f,CI opt)
            {
                RI i; for (i=0;i<lim;++i) if (i<rev[i]) swap(f[i],f[rev[i]]);
                for (i=1;i<lim;i<<=1)
                {
                    int m=i<<1,D=quick_pow(3,~opt?(mod-1)/m:mod-1-(mod-1)/m);
                    for (RI j=0;j<lim;j+=m)
                    {
                        int W=1; for (RI k=0;k<i;++k,W=1LL*W*D%mod)
                        {
                            int x=f[j+k],y=1LL*f[i+j+k]*W%mod;
                            f[j+k]=sum(x,y); f[i+j+k]=sub(x,y);
                        }
                    }
                }
                if (!~opt)
                {
                    int Inv=quick_pow(lim); for (i=0;i<lim;++i) f[i]=1LL*f[i]*Inv%mod;
                }
            }
            inline void inv(int *F,int *G,CI n)
            {
                if (n==1) return (void)(G[0]=quick_pow(F[0]));
                inv(F,G,n+1>>1); init(n<<1); copy(F,F+n,T);
                NTT(T,1); NTT(G,1); for (RI i=0;i<lim;++i)
                G[i]=1LL*sub(2,1LL*T[i]*G[i]%mod)*G[i]%mod;
                NTT(G,-1); fill(T+n,T+lim,0); fill(G+n,G+lim,0);
            }
        public:
            inline void get_inv(int *F,int *G,CI n)
            {
                for (lim=1;lim<=(n<<1);lim<<=1);
                fill(T,T+lim,0); fill(G,G+lim,0); inv(F,G,n);
            }
    }P;
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        File.read(n); File.read(r); invr=quick_pow(sub(1,r)); mtir=1LL*invr*r%mod;
        RI i; for (init(n),i=0;i<=n;++i) File.read(A[i]),F[i]=sum(mod,-1LL*inv[i]*mtir%mod);
        for (F[0]=1,P.get_inv(F,G,n+1),i=0;i<=n;++i) G[i]=1LL*G[i]*fact[i]%mod*invr%mod;
        for (i=0;i<=n;++i) ans=sum(ans,1LL*G[i]*A[i]%mod); return printf("%d",ans),0;
    }
    
  • 相关阅读:
    VScode出现无法打开“X”: 找不到文件(file:///XXXX) 的解决办法
    Re:0通过服务器自建内网穿透远程桌面(10分钟可完成)
    (补题 POJ 3013) Big Christmas Tree
    (补题 cf 1140)Detective Book
    (2019.9.5~2019.9.11)补题汇总(字符串相关)
    最小生成树(克鲁斯卡尔算法)
    最短路问题
    字符串匹配(部分整理)
    Linux内核分析——第八周学习笔记
    《Linux内核设计与实现》第四章读书笔记
  • 原文地址:https://www.cnblogs.com/cjjsb/p/10834881.html
Copyright © 2011-2022 走看看