zoukankan      html  css  js  c++  java
  • LOJ #2527 Luogu P4491「HAOI2018」染色

    好像网上没人....和我推出....同一个式子啊.....

    LOJ #2527 Luogu P4491


    题意

    $ n$个格子中每个格子可以涂$ m$种颜色中的一种

    若有$ k$种颜色恰好涂了$ s$格则产生$ w_k$的价值

    求所有涂色方案的价值和


    $ solution$

    按常规套路先容斥

    设 $f_x$表示恰好有$ x$种颜色涂了恰好$s$格的方案数,

    $ g_x$表示至少有$ x$种颜色涂了恰好$ s$格的方案数

    $ ans=sumlimits_{i=0}^mw_if_i$

    $ f_x=sumlimits_{i=x}^m (-1)^{i-x}inom{i}{x}g_i$

    $ g_x=inom{m}{x}inom{n}{sx}frac{(sx)!}{(s!)^x}(m-x)^{n-sx}$

    其中$ g_x$的意义即为选出$x$种颜色,选出$ sx$个格子放置这些颜色,

    并将其他$ m-x$种颜色在其他格子乱放的方案数

    因此有

    $ans=sumlimits_{i=0}^mw_isumlimits_{j=i}^m(-1)^{j-i}inom{j}{i}g_j$

    将组合数展开成阶乘得

    $ans=sumlimits_{i=0}^mw_isumlimits_{j=i}^m(-1)^{j-i}frac{j!}{i!(j-i)!}g_j$

    $F_x=frac{(-1)^x}{x}$,$G_x=g_xx!$

    则有

    $ans=sumlimits_{i=0}^mfrac{w_i}{i!}sumlimits_{j=i}^mF_{j-i}G_j$

    将$ F$或$ G$反转之后后式是一个卷积形式
    而$F$和$G$都可以快速计算
    $NTT$优化即可

    时间复杂度$ O(m log m + n)$


    $ my code$

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define p 1004535809
    #define rt register int
    #define ll long long
    using namespace std;
    inline char __getchar(){
        static const int IN_LEN = 1000000;
        static char buf[IN_LEN], *s, *t;
        return (s == t ? t = (s = buf) + fread(buf, 1, IN_LEN, stdin), (s == t ? -1 : *s++) : *s++);
    }
    #define getchar() __getchar()
    inline ll read(){
        ll x = 0; char zf = 1; char ch = getchar();
        while (ch != '-' && !isdigit(ch)) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    int i,j,k,m,n,x,y,z,cnt;
    int ksm(int x,int y){
        int ans=1;
        for(rt i=y;i;i>>=1,x=1ll*x*x%p)if(i&1)ans=1ll*x*ans%p;
        return ans;
    }
    int njc[10000010],jc[10000010];
    void init(int N){
        njc[0]=njc[1]=jc[0]=jc[1]=1;
        for(rt i=2;i<=N;i++)jc[i]=1ll*i*jc[i-1]%p;
        njc[N]=ksm(jc[N],p-2);
        for(rt i=N-1;i>=1;i--)njc[i]=1ll*njc[i+1]*(i+1)%p;
    }
    inline int C(int x,int y){return 1ll*jc[x]*njc[y]%p*njc[x-y]%p;}
    int w[100010],g[270010],f[270010],R[270010];
    void NTT(int n,int *A,int fla){
        for(rt i=0;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]);
        for(rt i=1;i<n;i<<=1){
            int w=ksm(3,(p-1)/2/i);
            for(rt j=0;j<n;j+=(i<<1)){
                int K=1;
                for(rt k=0;k<i;k++,K=1ll*K*w%p){
                    int x=A[j+k],y=1ll*K*A[i+j+k]%p;
                    A[j+k]=(x+y)%p;A[i+j+k]=(x-y)%p;
                }
            }
        }
        if(fla==-1){
            reverse(A+1,A+n);int invn=ksm(n,p-2);
            for(rt i=0;i<n;i++)A[i]=1ll*invn*A[i]%p;
        }
    }
    int main(){
        n=read();m=read();int s=read();
        ll ans=0;init(max(n,m));
        for(rt i=0;i<=m;i++)w[i]=read();
        for(rt j=0,invv=1;j<=m&&s*j<=n;j++,invv=1ll*invv*njc[s]%p)
        g[j]=1ll*C(m,j)*C(n,s*j)%p*jc[s*j]%p*invv%p*ksm(m-j,n-s*j)%p*jc[j]%p;
        
        for(rt i=0,tag=1;i<=m;i++,tag*=-1)f[i]=tag*njc[i];
        reverse(f,f+m+1);
        int lim=1;while(lim<=m+m)lim<<=1;
        for(rt i=1;i<lim;i++)R[i]=(R[i>>1]>>1)|(i&1)*(lim>>1);
        NTT(lim,f,1);NTT(lim,g,1);
        for(rt i=0;i<lim;i++)f[i]=1ll*f[i]*g[i]%p;
        NTT(lim,f,-1);
        for(rt i=0;i<=m;i++)(ans+=1ll*f[i+m]*w[i]%p*njc[i]%p)%=p;
        cout<<(ans+p)%p;
        return 0;
    }

     

  • 相关阅读:
    【笔记】DLHLP
    【笔记】DLHLP
    【笔记】DLHLP
    【笔记】DLHLP
    【笔记】PyTorch框架学习 -- 2. 计算图、autograd以及逻辑回归的实现
    【笔记】PyTorch框架学习 -- 1. 张量创建及操作,线性回归的实现
    【安装指南】pytorch相关软件安装
    【笔记】机器学习
    【笔记】机器学习
    【笔记】机器学习
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10070700.html
Copyright © 2011-2022 走看看