cf954H

挖我自闭了这是什么东西啊。

给出一棵深度为 n 的树,其中深度为 i 的节点有 a_i 个儿子。问树上的简单路径中长度在 1sim2n-2 之间的每个有多少条。

f_{i,j} 表示对于在 i 层的 1 个节点,向下走 j 步的方案数

g_{i,j} 表示对于在 i 层的 1 个节点,向上走 j 步的方案数

然后我们可以得到这样的递推式。

 f[i][j]=a[i]*f[i+1][j-1]);
g[i][j]=(j>=2)*(a[i-1]-1)*f[i][j-2]+g[i-1][j-1]);
显然对于一条路径会算两次。所以最终答案除以 2
 即可。
你以为这就完了?
下面才是自闭的开始。
256M大概能开6e7?记不清了。。。所以我们只能开一个[5000][9999]这样纸的数组,然后滚来滚去滚来滚去。
ac代码:
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod = 1e9+7;
 5 int n;
 6 int a[5001],c[5005];
 7 int f[5001][9999],ans[9999];
 8 int main(){
 9     ios::sync_with_stdio(false);
10     cin>>n;c[0]=1;
11     for(int i=1;i<n;i++)cin>>a[i];
12     for(int i=1;i<=n;i++)c[i]=1ll*a[i]*c[i-1]%mod;
13     for(int i=n;i>=1;i--){
14         f[i][0]=1;
15         for(int j=1;j<=n-i;j++){
16             f[i][j]=(1ll*a[i]*f[i+1][j-1])%mod;
17             ans[j]=(1ll*f[i][j]*c[i-1]+ans[j])%mod;
18         }
19     }
20     for(int i=1;i<=n;i++){
21         for(int j=2*n-2;j>=1;j--){
22             f[i][j]=f[i-1][j-1];
23             if(i>1&&j>1)
24                 f[i][j]=(1ll*(a[i-1]-1)*f[i][j-2]+f[i][j])%mod;
25             ans[j]=(1ll*f[i][j]*c[i-1]+ans[j])%mod;
26         }
27     }
28     for(int i=1;i<=2*n-2;i++){
29         cout<<(mod+1ll)*ans[i]/2%mod<<' ';
30     }
31 }
View Code

MLE ON TEST 01 代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod = 1e9+7;
 5 int n;
 6 int a[5001];
 7 int f[5001][5001],g[5001][9999];
 8 int main(){
 9     ios::sync_with_stdio(false);
10     cin>>n;a[0]=1;
11     for(int i=1;i<n;i++)cin>>a[i];
12     for(int i=1;i<=n;i++)
13        f[i][1]=a[i],f[i][0]=1;
14     for(int i=2;i<=n;i++)
15         g[i][1]=1,g[i][0]=1;
16     for(int i=n-1;i>=1;i--){
17         for(int j=2;j<=n-i;j++){
18             f[i][j]=(1ll*a[i]*f[i+1][j-1])%mod;
19         }
20     }
21     for(int i=2;i<=n;i++){
22         for(int j=2;j<=2*n-2;j++){
23             g[i][j]=(1ll*(j>=2)*(a[i-1]-1)*f[i][j-2]+g[i-1][j-1])%mod;
24         }
25     }
26     for(int i=1;i<=n;i++)a[i]=1ll*a[i]*a[i-1]%mod;
27     for(int i=1;i<=2*n-2;i++){
28         ll sum = 0;
29         for(int j=1;j<=n;j++){
30             sum=(sum+1ll*a[j-1]*(f[j][i]+g[j][i])%mod)%mod;
31         }
32         cout<<sum/2<<' ';
33     }
34 }
View Code
 
原文地址:https://www.cnblogs.com/MXang/p/10220686.html