CF997D


分析:

  假設在第一個樹上我們有一個長度為x的環,在第二樹上我們有一個長度為y的環,那么可以在叉積樹上構造出$\binom{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\n",ans);
81     return 0;
82 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM