随笔 - 18  文章 - 0  评论 - 2  阅读 - 408

legowall

毒瘤问题 (雾

首先我们可以先考虑一行的话有多少种方案,,这是一个经典问题答案就是斐波那契数列

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]

 

ps:有人在O(h*w)的复杂度完成了本题链接在这里: tmd牛逼

https://www.luogu.com.cn/blog/xiaoyaowudi/solution-p9318

 

代码如下:

复制代码
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)
}
复制代码

 

posted on   yl_neo  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示