• 【XSY3657】 因数分解


    【XSY3657】 因数分解

    DP+容斥神仙题!!!

    (b_i)要互不相同,这很烦,于是我们就先考虑让(b_i)可以相同,再容斥。

    另外,要让每个元素都不相同,最后再消去顺序。

    首先我们考虑到(sum m)很小,于是我们可以先对(n!)进行质因数分解,然后用背包DP算出每一种(sum b_i=m)的划分的分配质因数的方案数。具体来说,我们对每一种(b_i)的划分,考虑把每一个(b_i)当成元素且有无限个,然后进行背包DP,每一个次数为(q_i)(p_i)的贡献就会是由(b_i)组成(q_i)的方案数。

    之后我们考虑对于题目给定的(a_i),把其中钦定(b_i)相同的划分到同一组,并统计一下方案数,这个也可以用DP来解决。

    那么,对于每一种方案,它的贡献就是(分配质因数的方案数 imes 划分a_i的方案数 imes 容斥系数)

    于是来考虑容斥系数。

    不妨大胆假设,容斥系数只和划分到同一组的(a_i)的个数有关系,为(f(a_i))

    我们考虑对于每一种划分,我们只钦定了同一组里面的(b_i)相同,并未钦定不同组的(b_i)不同,于是考虑对于每一个(b_i)互不相同的划分,每一个(b_i)相同的组的大小为(s_i),那么这个划分的贡献有:

    [[s_1=s_2=...=s_k=1]=sum_{s_i划分为s'_1,s'_2,...,s'_{k_i}} prod_{i=1}^k frac{s_i!prod_{j=1}^{k_i}f(s'_j)}{k_i!prod_{j=1}^{k_i}s'_j!} ]

    其中,“(s_i)被划分为...”就意味着全部统计了(s_i)这种(b_i)互不相同划分的方案数。

    右边的那个阶乘式的贡献还是很显然的。

    考虑我们把每一个(s)提出来:

    [[s=1]=sum_{s划分为s_1,s_2,...,s_k} frac{s!prod_{i=1}^kf(s_i)}{k!prod_{i=1}^{k}s_i!} ]

    看到右边的右半部分,不难想到这是一个(EGF)的形式,于是设(F(x))(f)(EGF),则有:

    [ecause F(x)=sum_{i=0}^{infty} frac{f(i)}{i!}x^i\ herefore e^{F(x)}=sum_{i=0}^{infty} frac{F^i(x)}{i!}=sum_{i=0}^{infty}frac{(sum_{j=0}^{infty} frac{f(j)}{j!})^i}{i!}\ herefore [x^m]e^{F(x)}=sum_{x_1+x_2+...+x_k=m} frac{1}{k!}prod_{i=1}^kfrac{f(x_i)}{x_i!},m>0 ]

    看看上面那条式子,是不是很像?

    根据上面那条式子,有:

    [[m=1]=sum_{x_1+x_2+...+x_k=m} frac{m!}{k!}prod_{i=1}^kfrac{f(x_i)}{x_i!}\ herefore frac{[m=1]}{m!}=[m=1]=sum_{x_1+x_2+...+x_k=m} frac{1}{k!}prod_{i=1}^kfrac{f(x_i)}{x_i!}\ herefore [x^m]e^{F(x)}=[m=1] ]

    另外有特殊的一点,我们让(f(0)=0),于是就有([x^0]F(x)=0),所以([x^0]e^{F(x)}=1),那么(e^{F(x)}=1+x)

    则有:

    [F(x)=ln(1+x)\ herefore F'(x)=frac{1}{(1+x)}\ herefore F'(x)=sum_{i=0}^{infty} (-1)^ix^i\ herefore F(x)=sum_{i=0}^{infty} frac{(-1)^{i-1}}{i}x^i\ herefore frac{f(i)}{i!}=frac{(-1)^{i-1}}{i}\ herefore f(i)=(-1)^{i-1}(i-1)! ]

    至此,本题推导完毕。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline int dec(int x,int y){return x<y?x-y+mod:x-y;}
    inline int mul(int x,int y){return 1ll*x*y%mod;}
    inline int qpow(int n,int k){
        int ret=1;
        while(k){
            if(k&1)ret=mul(ret,n);
            n=mul(n,n);
            k>>=1;
        }
        return ret;
    }
    #define pii pair<int,int>
    #define mp make_pair
    #define fi first
    #define se second
    int mxn;
    int ss[10010];
    int tot;
    int prime[10010];
    bool vis[10010];
    int siz[10010];
    int fac[10010],ifac[10010];
    int calc(int n,int i){
        int ret=0;
        while(n){
            ret+=n/i;
            n/=i;
        }
        return ret;
    }
    void Euler(int n){
        fac[0]=1;
        for(int i=1;i<=n;++i)fac[i]=mul(fac[i-1],i);
        ifac[n]=qpow(fac[n],mod-2);
        for(int i=n-1;i>=0;--i)ifac[i]=mul(ifac[i+1],i+1);
        for(int i=2;i<=n;++i){
            if(!vis[i]){
                prime[++tot]=i;
                ss[i]=calc(n,i);
                siz[ss[i]]++;
                mxn=max(mxn,ss[i]);
            }
            for(int j=1;j<=tot&&i*prime[j]<=n;++j){
                vis[i*prime[j]]=true;
                if(i%prime[j]==0)break;
            }
        }
    }
    int n,m;
    int sum;
    int a[10010];
    int h[50][10010];
    map<vector<int>,int> divide;
    void dfs(int now,int st,int all,vector<int> D){
        if(all==sum){
            int ret=1;
            for(int i=1;i<=mxn;++i){
                ret=mul(ret,qpow(h[now][i],siz[i]));
            }
            divide[D]=ret;
            return;
        }
        for(int i=st;i+all<=sum;++i){
            if(i+all!=sum&&2*i+all>sum)continue;
            for(int j=0;j<=mxn;++j){
                h[now+1][j]=h[now][j];
            }
            for(int j=i;j<=mxn;++j){
                h[now+1][j]=add(h[now+1][j],h[now+1][j-i]);
            }
            D.push_back(i);
            dfs(now+1,i,i+all,D);
            D.pop_back();
        }
    }
    map<vector<pii>,int> dp[2];
    map<vector<pii>,int>::iterator it;
    int ans;
    void solve(){
        vector<pii> empty;
        empty.clear();
        int now=0,lst=1;
        dp[lst][empty]=1;
        for(int i=1;i<=m;++i){
            dp[now].clear();
            for(it=dp[lst].begin();it!=dp[lst].end();++it){
                vector<pii> nw;
                for(int j=0,up=(*it).fi.size();j<up;++j){
                    nw=(*it).fi;
                    nw[j].fi+=a[i];
                    nw[j].se++;
                    sort(nw.begin(),nw.end());
                    dp[now][nw]=add(dp[now][nw],(*it).se);
                }
                nw=(*it).fi;
                nw.push_back(mp(a[i],1));
                sort(nw.begin(),nw.end());
                dp[now][nw]=add(dp[now][nw],(*it).se);
            }
            now^=1,lst^=1;
        }
        for(it=dp[lst].begin();it!=dp[lst].end();++it){
            vector<pii> nw=(*it).first;
            vector<int> vec;
            vec.clear();
            int tmp=((m-nw.size())&1)?dec(mod,1):1;
            for(int i=0;i<nw.size();++i){
                vec.push_back(nw[i].fi);
                tmp=mul(tmp,fac[nw[i].se-1]);
            }
            ans=add(ans,mul(tmp,mul(divide[vec],(*it).se)));
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        Euler(n);
        for(int i=1;i<=m;++i){
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        h[0][0]=1;
        vector<int> empty;empty.clear();
        dfs(0,1,0,empty);
        sort(a+1,a+1+m);
        int sb=1,dv=1;
        for(int i=2;i<=m;++i){
            if(a[i]==a[i-1])sb++;
            else {
                dv=mul(dv,ifac[sb]);
                sb=1;
            }
        }
        dv=mul(dv,ifac[sb]);
        solve();
        printf("%d
    ",mul(ans,dv));
    }
    
  • 相关阅读:
    访问前端项目时Http请求变成了HTTPS
    Jenkins升级后无法正常启动(java.lang.IllegalStateException: An attempt to save the global configuration ......
    准备开始学习了。
    Nginx的安装与使用
    Linux 学习001
    Nginx为什么比Apache Httpd高效:原理篇
    Asp .Net Core Spa (二)
    Asp .Net Core Spa (一)
    基础笔记(三):网络协议之Tcp、Http
    跨平台运行ASP.NET Core 1.0
  • 原文地址:https://www.cnblogs.com/youddjxd/p/15110449.html
Copyright © 2020-2023  润新知