• 神经元(prufer序列+dp)


    题目描述:

    你培育出了一些新型的神经元,它们可以有很多的轴突。

    具体来说,对于第i个神经元,它有1~di条轴突,因此可以与1~di个神经元相连,可以将轴突看成无向图的边,假定每个神经元都是不同的。

    现在你想知道,有多少种方案使得其中恰好k个神经元相连通,这里的连通需要保证任意两个神经元间有且仅有一条路径,方案数可能很大,你只需要对10^9+7取模输出。

    两个方案是不同的当且仅当选择的神经元集合不同或其中有至少一条轴突(u,v)出现在一个方案但不出现在另一个方案。

    题解:

    首先了解一下prufer序列:https://www.cnblogs.com/zwfymqz/p/8869956.html

    由prufer序列的性质我们可以知道:

      每个长度为n-2的prufer序列对应一棵n个节点的无根树。

    因此,我们可以枚举符合条件的prufer序列个数。

    定义 dp[i][j][k] 表示考虑到第i个数,用了j个数,prufer序列长度为k的序列个数,

    dp时枚举下一个数选择几次即可。

     1 dp[0][0][0]=1;
     2     for(int i=0;i<n;i++){
     3         for(int j=0;j<=i;j++){
     4             for(int k=0;k<=n-2;k++){
     5                 if(dp[i][j][k]){
     6                     dp[i+1][j][k]+=dp[i][j][k];//此数不选
     7                     dp[i+1][j][k]%=MOD;
     8                     for(int cnt=0;cnt<=d[i+1]-1&&k+cnt<=n-2;cnt++){//枚举此数选几次
     9                         dp[i+1][j+1][k+cnt]+=dp[i][j][k]*c[k+cnt][k];//在k+cnt个位置中选k个按顺序放上一序列的数,其余位置放此数
    10                         dp[i+1][j+1][k+cnt]%=MOD;
    11                     }
    12                 }
    13             }
    14         }
    15     }

    所以,我们还要预处理一下c[][]数组(c[i][j]表示从i个数中选j个数的方案数),具体求法如下:

    1 void init(){
    2     for(int i=0;i<=n;i++){
    3         c[i][0]=1;
    4         for(int j=1;j<=i;j++){
    5             c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;//第i个数可选可不选
    6         }
    7     }
    8 }

    完整代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD=1e9+7;
    const int N=105;
    int n,d[N];
    ll c[N][N],dp[N][N][N];
    void init(){
        for(int i=0;i<=n;i++){
            c[i][0]=1;
            for(int j=1;j<=i;j++){
                c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
            }
        }
    }
    int main(){
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++){
            scanf("%d",&d[i]);
        }
        dp[0][0][0]=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<=i;j++){
                for(int k=0;k<=n-2;k++){
                    if(dp[i][j][k]){
                        dp[i+1][j][k]+=dp[i][j][k];
                        dp[i+1][j][k]%=MOD;
                        for(int cnt=0;cnt<=d[i+1]-1&&k+cnt<=n-2;cnt++){
                            dp[i+1][j+1][k+cnt]+=dp[i][j][k]*c[k+cnt][k];
                            dp[i+1][j+1][k+cnt]%=MOD;
                        }
                    }
                }
            }
        }
        printf("%d ",n);
        for(int i=2;i<=n;i++){
            printf("%lld ",dp[n][i][i-2]);
        }
        return 0;
    }
  • 相关阅读:
    异常处理机制
    如题
    MSSql随机取数据据
    在ASP.NET中下载Text文件,而不是在浏览器中打开它
    [原创]SQLite .net 数据库操作类
    对WinForm的App.config文件进行加密 转自 http://www.cnblogs.com/Jinjian/archive/2006/09/06/496009.html
    大型系统上PHP令人不爽的九大原因 转自:http://edu.itbulo.com/200705/114678.htm
    [原创]AspNetPager GridView 直连数据库 分页列子
    用.NET读取Flash格式文件信息
    js调用php动态数据
  • 原文地址:https://www.cnblogs.com/HarryPotter-fan/p/11405823.html
Copyright © 2020-2023  润新知