zoukankan      html  css  js  c++  java
  • 【题解】Loj #2504.「2018 集训队互测 Day 5」小 H 爱染色 [*medium]

    显然答案为:

    [sum_{i=1}^{n}F(i)left({n-i+1choose m}^2-{n-ichoose m}^2 ight) ]

    因为 ({nchoose m}) 是一个关于 (n)(m) 次多项式,又因为 (n) 次多项式的前缀和是 (n+1) 次多项式。所以上式其实是一个 (3m+1) 次多项式。

    不难想到令:

    [f(k)=sum_{i=1}^{k}F(i)left({n-i+1choose m}^2-{n-ichoose m}^2 ight) ]

    然后求 (f(0),f(1),f(2),cdots,f(3m+1)) 后线性插值即可。

    (f) 是个次数不超过 (m) 的多项式,现在要快速求出 (f(m+1))(f(3m+1))

    考虑拉格朗日插值的式子:

    [egin{aligned} f(k)&=sum_{i=0}^{m}f(i)prod_{i ot= j}frac{x-j}{i-j}\ &=sum_{i=0}^{m}f(i)frac{prod_{i ot= j}(x-j)}{prod_{i ot= j}(i-j)}\ end{aligned} ]

    显然下面的 (prod_{i ot= j}(i-j)) 预处理阶乘后可以 (O(1)) 算,令 (g(i)=frac{f(i)}{prod_{i ot= j}(i-j)}) ,有:

    [egin{aligned} f(k)&=sum_{i=0}^{m}g(i)prod_{i ot= j}(x-j)\ &=sum_{i=0}^{m}g(i)prod_{j=0}^{m}(x-j)frac{1}{(x-i)}\ &=prod_{j=0}^{m}(x-j)sum_{i=0}^{m}g(i)frac{1}{x-i}\ &=x^{underline{m+1}}sum_{i=0}^{m}g(i)frac{1}{x-i}\ end{aligned} ]

    (式子没列清除导致这里想了好久,最后想出来个线段树做法,感觉不行。瞅了眼题解才发现就是个简单卷积 >_<

    后面的直接 ( m{NTT}) 卷就好了。 时间复杂度 (O(mlog m))

    // {{{ Poly
    
    const int LogN=26;
    
    namespace Poly {
        int tim,lim,inv[LogN],w[1<<24|5];
        poly rev[LogN];
    
        inline void init_r(int len) {
            for(lim=1,tim=0;lim<len;lim<<=1,++tim);
            if(rev[tim].size()) return ;
            rev[tim].rez(lim),inv[tim]=modpow(lim,mod-2);
            for(int i=0;i<lim;++i) rev[tim][i]=(rev[tim][i>>1]>>1)|((i&1)<<(tim-1));
        }
        
        inline int W(int a,int b) {
            return modpow(modpow(3,(mod-1)>>(a+1)),b);
        }
        inline void NTT(poly &f,int typ) {
            static ull g[1<<24|5];
            for(int i=0;i<lim;++i) g[rev[tim][i]]=f[i];
    
            for(int p=1,s=0,t=0;p<lim;p<<=1,++t) {
    
                w[0]=1,w[1]=modpow(3,(mod-1)>>(t+1));
                lep(i,2,p) w[i]=mul(w[i-1],w[1]);
    
                for(int k=0;k<lim;k+=p<<1)
                    for(int l=k;l<k+p;++l)
                        s=mul(g[l+p]%mod,w[l-k]),g[l+p]=g[l]+mod-s,g[l]+=s;
            }
    
            for(int i=0;i<lim;++i) f[i]=g[i]%mod;
            if(~typ) return ;
            std::reverse(++f.begin(),f.end());
            for(int i=0;i<lim;++i) f[i]=mul(f[i],inv[tim]);
        }
        
        inline poly operator * (poly a,poly b) {
            int n=a.size(),m=b.size(),t=n+m-1;
            init_r(t);
            a.rez(lim),NTT(a,1);
            b.rez(lim),NTT(b,1);
            for(int i=0;i<lim;++i) a[i]=mul(a[i],b[i]);
            return NTT(a,-1),a.rez(t),a;
        }
    }
    
    using Poly::operator *;
    
    // }}}
    
    const int N=4e6+5;
    int n,m,l,f[N],inv[N],fac[N];
    
    inline void init() {
        fac[0]=1;
        lep(i,1,l) fac[i]=mul(fac[i-1],i);
        inv[l]=modpow(fac[l],mod-2);
        rep(i,l,1) inv[i-1]=mul(inv[i],i);
    }
    
    inline void solve1() { /*get f(m+1~3m+1)*/
        poly p,g; g.rez(m+1),p.rez(l+1);
        lep(i,0,m) g[i]=mul(f[i],mul(inv[i],((m-i)&1)?mod-inv[m-i]:inv[m-i]));
        lep(i,0,l) p[i]=modpow(i,mod-2);
    
        poly h=p*g;
        int t=fac[m+1];
        lep(k,m+1,l) f[k]=mul(h[k],t),t=mul(t,mul(k+1,p[k-m]));
    }
    
    inline void solve2() {
        static int d[N];
    
        int s1=1,s2=1;
        lep(i,0,m-1) s1=mul(s1,n-i+1),s2=mul(s2,n-i);
    
        #define S(x) mul(x,x)
        lep(i,0,l) {
            if(i) d[i]=d[i-1];
            pls(d[i],mul(f[i],dec(S(mul(s1,inv[m])),S(mul(s2,inv[m])))));
            
            s1=s2,s2=(n-i>m)?mul(s2,mul(n-m-i,modpow(n-i,mod-2))):0;
        }
        #undef S
        
        if(n<=l) return printf("%d
    ",d[n]),void();
    
        int ans=0,res=1;
        lep(i,0,l) res=mul(res,dec(n,i));
        lep(i,0,l) d[i]=mul(d[i],mul(inv[i],((l-i)&1)?mod-inv[l-i]:inv[l-i]));
        lep(i,0,l) pls(ans,mul(mul(res,modpow(dec(n,i),mod-2)),d[i]));
        printf("%d
    ",ans);
    }
    
    int main() {
        IN(n,m),l=3*m+1,--n;
        lep(i,0,m) IN(f[i]);
        
        init();
        solve1();
        solve2();
        return 0;
    }
    
  • 相关阅读:
    (转)C# DllImport的用法
    (转)C#网络编程(异步传输字符串) Part.3
    (转)C#网络编程(订立协议和发送文件) Part.4
    C# tostring()汇总
    (转)C#网络编程(基本概念和操作) Part.1
    (转)关于数据库存储过程分页DatagridView BindingNavigator 控件的详细实现
    C# sql server 数据库备份和还原
    (转)C#网络编程(接收文件) Part.5
    2010年5月学习计划
    APUE学习笔记 Chapter 2 . Unix Standardization and Implementations
  • 原文地址:https://www.cnblogs.com/losermoonlights/p/13777358.html
Copyright © 2011-2022 走看看