HDU - 6185 Covering

版权声明: https://blog.csdn.net/moon_sky1999/article/details/88022333

题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=6185

思路来自:https://blog.csdn.net/elbadaernu/article/details/77825979

对于每个f[i],大致可以分成5种情况进行转移。推导式子的过程如下:

/*
 1.
 1000
 1000
 2000
 2000

 f[i-1]

 2.
 1000
 1000
 2200
 3300

 f[i-2]+f[i-3]+...+f[1]

 3.
 1100
 2200
 3300
 4400

 f[i-2]

 4.
 1100
 2200
 3000
 3000

 f[i-2]+f[i-3]+...+f[1]

 5.
 1100
 2000
 2000
 3300

 f[i-2]+f[i-4]+...+f[2/1]


 (1)f[i]=f[i-1]+f[i-2]+2*(f[i-2]+f[i-3]+...+f[1])+(f[i-2]+f[i-4]+...+f[2/1])
 带入i-2
 (2)f[i-2]=f[i-3]+f[i-4]+2*(f[i-4]+...+f[1])+(f[i-4]+...+f[2/1])
 两式左右相减
 f[i]-f[i-2]=f[i-1]+f[i-2]-f[i-3]-f[i-4]+2*(f[i-2]+f[i-3])+f[i-2]
 化简可得:
 f[i]=f[i-1]+5*f[i-2]+f[i-3]-f[i-4]

 */

构造矩阵

1 5 1 -1
1 0 0 0
0 1 0 0
0 0 1 0

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

#define ll long long
#define ull unsigned long long
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)

const ll mod = 1e9 + 7;

using namespace std;

int m = 4;

struct matrix {
    ll num[5][5];

    matrix() { memset(num, 0, sizeof num); }

    matrix operator*(const matrix &x) {
        matrix c;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= m; ++j) {
                for (int k = 1; k <= m; ++k) {
                    c.num[i][j] = (c.num[i][j] + num[i][k] * x.num[k][j] + mod) % mod;
                }
            }
        }
        return c;
    }

    matrix &operator=(const matrix &x) {
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= m; ++j) {
                num[i][j] = x.num[i][j];
            }
        }
        return *this;
    }
};

matrix pow_mod(matrix &x, ll k) {
    matrix ans;
    for (int i = 1; i <= m; ++i) {
        ans.num[i][i] = 1;
    }
    while (k) {
        if (k & 1)ans = ans * x;
        x = x * x;
        k >>= 1;
    }
    return ans;
}

int main() {
    ll n;
    ll f[5];
    f[1] = 36;
    f[2] = 11;
    f[3] = 5;
    f[4] = 1;
    while (~scanf("%lld", &n)) {
        matrix a;
        a.num[1][1] = 1;
        a.num[1][2] = 5;
        a.num[1][3] = 1;
        a.num[1][4] = -1;
        a.num[2][1] = 1;
        a.num[3][2] = 1;
        a.num[4][3] = 1;
        if (n <= 4) {
            printf("%lld\n", f[4 - n + 1]);
            continue;
        }
        matrix b = pow_mod(a, n - 4);
        ll ans = 0;
        for (int i = 1; i <= 4; ++i) {
            ans += b.num[1][i] * f[i];
            ans += mod;
            ans %= mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/88022333