# HDU - 6185 Covering

题意

有一个4xN的土地,用2x1 和1x2两种去无重叠覆盖,问最多有多少种方案。

思路

最开始我以为是奇数和偶数分别讨论,推出来的公式是(偶数) f[i] = f[2]^(i/2); (奇数)f[i] = 5 * f[i-1],推出来不久我就意识到好像貌似是错的。然后暴力把前面的答案找到 1 5 11 36 95 ...,再者第一次推的时候也有部分是对的,所以容易得到一个线性方程
f[i] = f[i-1] +5*f[i-2]+f[i-3] -f[i-4];
第二个问题是数据很大,套了一个矩阵快速幂的模板。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const long long MOD = 1e9 + 7;
LL aaa[30] =
{
    1, 5, 1, -1, 0,
    1, 0, 0, 0, 0,
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 0, 1, 0
};
struct matrix
{
    LL a[5][5];
};

matrix mat_mul(matrix x, matrix y)
{
    matrix res;
    memset(res.a, 0, sizeof(res.a));
    for(int i = 0; i < 5; i++)
        for(int j = 0; j < 5; j++)
            for(int k = 0; k < 5; k++)
            {
                res.a[i][j] += x.a[i][k] * y.a[k][j] ;
                res.a[i][j] =(res.a[i][j] %MOD + MOD) % MOD;
            }
    return res;
}

matrix mat_pow(LL n)
{
    matrix c, res;  //  res = c ^ n
    int ind = 0;
    for(int i = 0; i < 5; i++)
        for(int j = 0; j < 5; j++)
            c.a[i][j] = aaa[ind++];
    memset(res.a, 0, sizeof(res.a));
    for(int i = 0; i < 5; i++)
        res.a[i][i] = 1;
    while(n)
    {
        if(n & 1)
            res = mat_mul(res, c);
        c = mat_mul(c, c);
        n = n >> 1;
    }
    return res;
}
LL cc[6] = {1, 5, 11, 36, 95};
matrix ff ;
int main()
{

    for(int i = 0; i < 5; i ++)
        ff.a[4 - i][0] = cc[i];
    long long n;
    while(cin >> n)
    {
        if(n > 5)
        {
            matrix num = mat_pow(n - 5);
            matrix mum = mat_mul(num, ff);
            cout << mum.a[0][0] << endl;
        }
        else
            cout << cc[n - 1] << endl;
    }
    return 0;
}
posted @ 2018-08-17 09:54  cifiyoo  阅读(85)  评论(0编辑  收藏  举报