• CF997D


    分析:

      假设在第一个树上我们有一个长度为x的环,在第二树上我们有一个长度为y的环,那么可以在叉积树上构造出$inom{x+y}{x}$个长度为x+y的环

      问题的关键就变成了如何统计出在一个树上的长度为i的环的个数

      设$f(u,v,k)$表示从u点出发走k步回到u点,中途不经过点v的方案数,其中v是u的相邻点

      考虑求解的转移过程,一定是从u走到某个邻接点w(w!=v),然后从w走到w(不经过u),然后再回到u,于是有转移方程

      

      这个是$O(n^2k^2)$的,但明显里面的w不需要枚举,只需要拿sum减去w=v的情况就行了,于是变成了$O(nk^2)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mp make_pair
     4 const int maxn=4000,mod=998244353;
     5 int k;
     6 int ans;
     7 int C[80][80];
     8 void inc(int &a,int b)
     9 {
    10     a=(a+b)%mod;
    11 }
    12 struct wjmzbmr
    13 {
    14     int n;
    15     vector<int> g[maxn+5];
    16     vector<int> dp[80][maxn+5];
    17     int sum[80][maxn+5];
    18     int ans[maxn+5],sz[maxn+5];
    19     map<pair<int,int>,int> s;
    20     void init()
    21     {
    22         for(int i=1;i<n;++i)
    23         {
    24             int u,v;
    25             scanf("%d%d",&u,&v);
    26             g[u].push_back(v),g[v].push_back(u);
    27         }
    28         for(int i=1;i<=n;++i)
    29             for(int j=0;j<g[i].size();++j)
    30                 s[mp(i,g[i][j])]=j;
    31         for(int i=1;i<=n;++i) sz[i]=g[i].size(),g[i].push_back(0);
    32         for(int t=0;t<=k;++t)
    33             for(int i=0;i<=n;++i)
    34                 dp[t][i].resize(sz[i]+1,0);
    35     }
    36     void work()
    37     {
    38         for(int i=1;i<=n;++i)
    39             for(int j=0;j<=sz[i];++j)
    40             {
    41 
    42                 dp[0][i][j]=1;
    43                 inc(sum[0][g[i][j]],1);
    44             }
    45         for(int i=2;i<=k;++i)
    46             for(int u=1;u<=n;++u)
    47                 for(int j=0;j<=sz[u];++j)
    48                 {
    49                     int v;
    50                     if(j<sz[u]) v=g[u][j];else v=0;
    51                     int id;
    52                     if(v==0) id=0;
    53                     else
    54                         id=s[mp(v,u)];
    55                     for(int t=0;t<=i-2;++t)
    56                         dp[i][u][j]=((dp[i][u][j]+1LL*dp[i-t-2][u][j]*(sum[t][u]-dp[t][v][id])%mod)%mod+mod)%mod;
    57                     inc(sum[i][v],dp[i][u][j]);
    58                 }
    59         for(int i=0;i<=k;i+=2)
    60             for(int u=1;u<=n;++u)
    61                 inc(ans[i],dp[i][u][sz[u]]);
    62     }
    63 }tree[2];
    64 int main()
    65 {
    66     //freopen("ce.in","r",stdin);
    67     scanf("%d%d%d",&tree[0].n,&tree[1].n,&k);
    68     tree[0].init(),tree[1].init();
    69     tree[0].work();
    70     tree[1].work();
    71     C[0][0]=1;
    72     for(int i=1;i<=k;++i)
    73     {
    74         C[i][0]=1;
    75         for(int j=1;j<=i;++j)
    76             C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    77     }
    78     for(int i=0;i<=k;++i)
    79         inc(ans,int(1LL*tree[0].ans[i]*tree[1].ans[k-i]%mod*C[k][i]%mod));
    80     printf("%d
    ",ans);
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    C++中整型变量的存储大小和范围
    A1038 Recover the Smallest Number (30 分)
    A1067 Sort with Swap(0, i) (25 分)
    A1037 Magic Coupon (25 分)
    A1033 To Fill or Not to Fill (25 分)
    A1070 Mooncake (25 分)
    js 获取控件
    C#代码对SQL数据库添加表或者视图
    JS 动态操作表格
    jQuery取得下拉框选择的文本与值
  • 原文地址:https://www.cnblogs.com/wmrv587/p/9258527.html
Copyright © 2020-2023  润新知