HDU 6185 Covering 矩阵快速幂 递推

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

  题目描述: 一个4*n的矩形, 你用1*2的矩形覆盖有多少种方案, n <= 1e18

  解题思路: 自己看题一开始以为是轮廓线DP, 后来发现n实在是太大了....数组根本开不下, 后来觉得应该是一个矩阵快速幂, 可是递推式自己求不出来。 其实递推式应该打表出前十个n再去求, 因为我们这是一个线性递推式

    f(n) = k1 * f(n-1) + k2 * f(n-2) + ......  kw * f(n-w)

  我们从f(n-1) + f(n-2) 开始去找, 如果找到的k都是整数的话, 那这个递推式就是正确的, 因为这个递推式的几何意义表示在完成f(n-w)的前提下 前面那些有多少种方案, 而方案数一定是整数, 所以保证了正确性........现在我们先借助求得的前十个答案来求k, 当w = 2 , 3的情况下k都存在小数, 当w = 4的时候全部是整数

  代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <stack>
#include <deque>
#include <map>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define sca(x) scanf("%d",&x)
#define de printf("=======\n")
typedef long long ll;
using namespace std;

const int maxn = 105;
typedef double Matrix[maxn][maxn];
Matrix A, X;

void gauss(Matrix A,int n)
{
    int i,j,k,r;
    for(int i=0; i<n; i++)
    {
        r=i;
        for( j=i+1; j<n; j++)
            if(fabs(A[j][i])>fabs(A[r][i]))r=j;
        if(r!=i)
            for(j=0; j<=n; j++)swap(A[r][j],A[i][j]);
        for(k=i+1; k<n; k++)
        {
            double f=A[k][i]/A[i][i];
            for(j=i; j<=n; j++)
                A[k][j]-=f*A[i][j];
        }
    }
    for(i=n-1; i>=0; i--)
    {
        for(j=i+1; j<n; j++)
            A[i][n]-=A[j][n]*A[i][j];
        A[i][n]/=A[i][i];
    }
}

int main() {
    mem0(A);
    A[0][0]=95,A[0][1]=36,A[0][2]=11,A[0][3]=5,A[1][0]=6336,A[1][1]=2245,A[1][2]=781;
    A[1][3]=281,A[2][0]=781,A[2][1]=281,A[2][2]=95,A[2][3]=36,A[3][0]=2245,A[3][1]=781;
    A[3][2]=281,A[3][3]=95,A[0][4]=281,A[1][4]=18061,A[2][4]=2245,A[3][4]=6336;
    gauss(A, 4);
    for( int i = 0; i < 4; i++ ) {
        cout << A[i][4] << endl;
    }
    return 0;
}
求矩阵快速幂的系数

  系数是1, 5, 1, -1, 所以递推式就是f(n) = f(n-1)+5f(n-2)+f(n-3)-f(n-4)

  这时候我们就可以根据这个求矩阵快速幂的矩阵了...........

  写了一个多点儿......又出现BUG了.....不容易啊....

  代码: 

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <stack>
#include <deque>
#include <map>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define sca(x) scanf("%d",&x)
#define de printf("=======\n")
typedef long long ll;
using namespace std;

const ll mod = 1e9+7;
const int maxn = 4;
const int temp = 4;
const int a[4] = {36,11,5,1};
typedef struct {
    ll mat[maxn][maxn];
    void init() {
        mem0(mat);
        for( int i = 0; i < temp; i++ ) {
            for( int j = 0; j < temp; j++ ) {
                if( i == j ) mat[i][j] = 1;
            }
        }
    }
} Matrix;

Matrix matrix = {1,5,1,-1,1,0,0,0,0,1,0,0,0,0,1,0};

Matrix mul( Matrix m1, Matrix m2 ) {
    Matrix ret;
    mem0(ret.mat);
    for( int i = 0; i < temp; i++ ) {
        for( int j = 0; j < temp; j++ ) {
            for( int k = 0; k < temp; k++ ) {
                ret.mat[i][j] = (ret.mat[i][j] + (m1.mat[i][k]*m2.mat[k][j])+mod) % mod;
                //                cout << ret.mat[i][j] << endl;
            }
        }
    }
    return ret;
}

Matrix matrix_quick_power( Matrix m, ll times ) {
    Matrix ret;
    ret.init();
    while( times ) {
        if( times & 1 ) ret = mul( ret, m );
        times >>= 1;
        m = mul(m, m);
    }
    return ret;
}


int main() {
    //    debug(matrix);
    //    debug(matrix_quick_power( matrix, 1));
    ll n;
    while( cin >> n ) {
        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;
        }
        else {
            Matrix res;
            res.init();
            res = matrix_quick_power(matrix, n-4);
            ll ans = 0;
            for( int i = 0; i < 4; i++ ) {
                ans = (ans + res.mat[0][i]*a[i] + mod) % mod;
            }
            cout << ans << endl;
        }
    }
    return 0;
}
矩阵快速幂

  思考: 这里明确一个问题, 我看到其他博客里会有这样的写法, typedef double Matrix[4][4], 这里解释一样, 这个时候Matrix 代表的就是一个4*4的整型数组, Matrix A , A就是那个数组, 但是和二维数组不一样的是, 这里的A可以传进函数里做实参, 但是为什么呢?, 然后我看到函数声明是这样显示的 double (*A)[], 这样就能作为实参传进去了吗........我还是很弱, 得多学点儿......真的菜................||分割 分割 分割||  刚才学长在群里说了一下想明白了......原来传的就是一个指针........如果想传实参的话用vector<vector<double>>就可以了.....OK, 过

posted on 2017-09-01 13:39  FriskyPuppy  阅读(310)  评论(0编辑  收藏  举报

导航