毒瘤问题 ~雾~
首先我们可以先考虑一行的话有多少种方案,,这是一个经典问题答案就是斐波那契数列
f[i]=f[i-1]+f[i-2],那么如果我们考虑 H 高怎么样?因为有 H 的高度,故还要进行 H次幂。
让dp[i] 表示处理到第 i 列有多少个方案
那么转移方式就是 dp[i]=fib[i]-sum(dp[j]*fib[i-j]) j->[0,i-1]
最终答案是dp[w], 复杂度O(w^2)
如何w大呢? 我们就做O(w*h^2)
让dp[i][j]表示如果走了i列有j个2x1x1的lego
那么dp[1][i]=C(h,i)
转移方式为: dp[i][j]=sum(dp[i-1][k]*C(h-k,j)) for k->[1,h-j]
答案为 dp[w][0]
代码:
int w, h; cin >> w >> h; /* 突然联想到斐波那契数列: fib[n]=fib[n-1]+fib[n-2] 但是既然他需要h高,那么我们就需要快速幕了 */ if (h * h >= w) { vector<Mint> fib(w + 4), dp(w + 4); fib[1] = 1; fib[2] = 2; for (int i = 3; i <= w + 3; i++) fib[i] = fib[i - 1] + fib[i - 2]; for (int i = 0; i <= w + 3; i++) fib[i] = power(fib[i], h); for (int i = 1; i <= w; i++) { Mint sum = 0; for (int j = 1; j < i; j++) sum += dp[j] * fib[i - j]; dp[i] = fib[i] - sum; } cout << dp[w] << '\n';//O(w^2 * h) } /* 让dp[i][j]表示第i列里有j个2x1x1的legooooo 当我们枚举 dp[i][j]: dp[i][j]= 任何k->[0,h-k] : dp[i-1][k]*C(h-k,j)的和 答案就是 dp[w][0] */ else { vector<vector<Mint>> dp(w + 4, vector<Mint>(h + 4)); for (int i = 0; i <= h; i++) dp[1][i] = C(h, i); for (int i = 2; i <= w; i++) { for (int j = 0; j <= h; j++) { for (int k = 1; k <= h - j; k++) { dp[i][j] = dp[i][j] + dp[i - 1][k] * C(h - k, j); } } } cout << dp[w][0] << '\n';//O(h^2 * w) }
标签:vector,int,sum,fib,legowall,答案,dp From: https://www.cnblogs.com/yonglicp/p/17558674.html