首页 > 其他分享 >legowall

legowall

时间:2023-07-16 22:00:49浏览次数:42  
标签:vector int sum fib legowall 答案 dp

毒瘤问题 ~雾~

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

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

相关文章