挖我自闭了这是什么东西啊。
给出一棵深度为 的树,其中深度为 的节点有 个儿子。问树上的简单路径中长度在 之间的每个有多少条。
表示对于在 层的 个节点,向下走 步的方案数
表示对于在 层的 个节点,向上走 步的方案数
然后我们可以得到这样的递推式。
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 }
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 }