Fabricating Sculptures 题解

草草地写一篇题解,废话不多说

暴力

要拼成“^”型,考虑 \(DP\)

\(f_{i,j}\) 表示,总共有 \(i\) 个积木,其中底座占了 \(j\) 个积木,也就是说你还有 \(i-j\) 个积木来拼底座的上方。

转移方程:\(f_{i,j} = \sum\limits_{k=1}^{j} f_{i-j,k} (j-k+1)\)

初始化:\(f_{1,1}=1, f_{i,i}=1\),其中 \(i \le m\)

代码如下

#include <iostream>

using namespace std;

const int N = 5010;

int n, m;
int f[N][N];

int main()
{
	cin >> m >> n;
	f[1][1] = 1;
	for (int i = 1; i <= m; i ++ ) f[i][i] = 1;
	for (int i = 2; i <= n; i ++ )
	{
		for (int j = 1; j <= min(i - 1, m); j ++ )
		{
			for (int k = 1; k <= j; k ++ )
			{
				f[i][j] += f[i - j][k] * (j - k + 1);
			}
		}
//		if (i <= m) f[i][i] = 1;
	}
	cout << f[n][m] << endl;
}

然而 \(TLE\) 了。

前缀和优化

\(sum1_{i,j} = \sum\limits_{j=1}^m f_{i,j},\ sum2_{i,j} = j\sum\limits_{j=1}^m f_{i,j}\)

那么新的状态转移方程变成了:\(f_{i,j} = (j+1)sum1_{i-j,j} - sum2_{i-j,j}\)

#include <iostream>

using namespace std;

typedef long long LL;
const int N = 5010;
const LL mod = 1e9 + 7;

LL n, m;
LL f[N][N], sum1[N][N], sum2[N][N];

int main()
{
	cin >> m >> n;
	f[1][1] = 1;
	for (int i = 1; i <= m; i ++ ) f[i][i] = 1;
	for (LL i = 1; i <= n; i ++ )
	    sum1[1][i] = sum2[1][i] = 1;
	for (LL i = 2; i <= n; i ++ )
	{
	    for (LL j = 1; j <= min(i - 1, m); j ++ )
	        f[i][j] = ((j + 1) * sum1[i - j][j] - sum2[i - j][j]) % mod;
//		if (i <= m) f[i][i] = 1;
	    for (LL j = 1; j <= m; j ++ )
	    {
	        sum1[i][j] = (sum1[i][j - 1] + f[i][j]) % mod;
	        sum2[i][j] = (sum2[i][j - 1] + f[i][j] * j) % mod;
	    }
	}
	cout << f[n][m] << endl;
}
posted @ 2022-10-21 21:47  LittleMoMol  阅读(18)  评论(0编辑  收藏  举报
*/