HDU-6185(Covering)

先暴力打表找规律:

#include <iostream>

using namespace std;

int xx, yy;
const int MAXN = 1000;
int visit[4][MAXN];
int ans;
int dis[2][2] = {1, 0, 0, 1};
void f(int n){
    for(int i = 0; i < 4; ++i){
        for(int j = 0; j < n; ++j){
            if(visit[i][j] == 0) {
                xx = i;
                yy = j;
                return ;
            }
        }
    }
}

bool c(int n){
    for(int i = 0; i < 4; ++i){
        for(int j = 0; j < n; ++j){
            if(visit[i][j] == 0){
                return false;
            }
        }
    }
    return true;
}
void dfs(int x, int y, int n){
    if(c(n)){
        ans ++;
        return;
    }
    if(visit[x][y] == 0){
        for(int i = 0; i < 2; ++i){
            int dx = x + dis[i][0];
            int dy = y + dis[i][1];

            if(dx < 4 && dy < n && visit[dx][dy] == 0){
                visit[dx][dy] = 1;
                visit[x][y] = 1;
                f(n);
                dfs(xx, yy, n);
                visit[dx][dy] = 0;
                visit[x][y] = 0;
            }
        }
    }
}
int main(){
    for(int i = 1; i <= 15; ++i){
        ans = 0;
        dfs(0, 0, i);
        cout << ans << endl;
    }
}

发现前8项分别为:

1 5 11 36 95 281 781 2245

找规律:
列方程组:

theta0 * f1 + theta1 * f2 + theta3 * f3 + theta4 * f4 = f5

theta1 * f2 + theta1 * f3 + theta3 * f4 + theta4 * f5 = f6

theta2 * f3 + theta1 * f4 + theta3 * f5 + theta4 * f6 = f7

theta3 * f4 + theta1 * f5 + theta3 * f6 + theta4 * f7 = f8

高斯消元:

#include <iostream>
#include <cstring>
using namespace std;

const int MAXN = 4;
double theta[MAXN];
double a[MAXN][MAXN + 1];
void guass(int n){
    memset(theta, 0, sizeof(theta));
    for(int k = 1; k < n; ++k){
        for(int i = k + 1; i <= n; ++i){
            double l = a[i][k]/a[k][k];
            for(int j = k + 1; j <= n + 1; ++j){
                a[i][j] -= l*a[k][j];
            }
        }
    }
    for(int i = n; i >= 1; --i){
        double b = a[i][n+1];
        for(int j = i+1; j <= n; ++j){
            b -= a[i][j]*theta[j];
        }
        theta[i] = b/a[i][i];
    }
    for(int i = 1; i <= n; ++i)printf("theta%d = %f\n", i, theta[i]);
}
int main(){
    for(int i = 1; i <= 4; ++i)
        for(int j = 1; j <= 5; ++j) cin >> a[i][j];
    guass(4);
    return 0;
}

得到结果:

theta0 = -1, theta1 = 1, theta2 = 5, theta3 = 1

所以递推式为:

F[n] = F[n-1] + 5F[n-2] + F[n-3] - F[n-4]

根据矩阵快速幂求解:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long ll;
const ll MOD = 1000000007;
struct _Matrix{
    int size;
    ll matrix[10][10];
    _Matrix(int _size){
        size = _size;
    }
    _Matrix(){
        size = 10;
    }
    void init0(){
        memset(matrix, 0, sizeof(matrix));
    }
    void init1(){
        memset(matrix, 0, sizeof(matrix));
        for(int i = 0; i < size; ++i) matrix[i][i] = 1;
    }
    _Matrix Mutiple(_Matrix rhs){
        _Matrix result(4);
        for(int i = 0; i < size; ++i){
            for(int j = 0; j < size; ++j){
                result.matrix[i][j] = 0;
                for(int k = 0; k < size; ++k){
                    result.matrix[i][j] += (rhs.matrix[i][k] * matrix[k][j] + MOD)%MOD;
                    result.matrix[i][j] %= MOD;
                }
            }
        }
        return result;
    }
};

_Matrix qpow(_Matrix a, ll b){
    _Matrix m(4);
    m.init1();
    while(b){
        if(b&1) m = a.Mutiple(m);
        a=a.Mutiple(a);
        b >>= 1;
    }
    return m;
}

int main(){
    _Matrix t(4);
    t.init0();
    t.matrix[0][0] = 1;
    t.matrix[0][1] = 5;
    t.matrix[0][2] = 1;
    t.matrix[0][3] = -1;
    t.matrix[1][0] = 1;
    t.matrix[2][1] = 1;
    t.matrix[3][2] = 1;
    ll n;

    while(cin >> n){
        _Matrix ans(4);

        if(n > 4){
            ans = qpow(t, n-4l);
            ll p = (ans.matrix[0][0]*36%MOD + ans.matrix[0][1]*11%MOD + ans.matrix[0][2]*5%MOD + ans.matrix[0][3]%MOD)%MOD;
            cout << p << endl;
        }else if(n == 1) cout << 1 << endl;
        else if(n == 2) cout << 5 << endl;
        else if(n == 3) cout << 11 << endl;
        else if(n == 4) cout << 36 << endl;

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37753409/article/details/81046757
今日推荐