1. 程式人生 > >poj3734——矩陣快速冪入門題

poj3734——矩陣快速冪入門題

Blocks
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7111 Accepted: 3443

Description

Panda has received an assignment of painting a line of blocks. Since Panda is such an intelligent boy, he starts to think of a math problem of painting. Suppose there are N blocks in a line and each block can be paint red, blue, green or yellow. For some myterious reasons, Panda want both the number of red blocks and green blocks to be even numbers. Under such conditions, Panda wants to know the number of different ways to paint these blocks.

Input

The first line of the input contains an integer T(1≤T≤100), the number of test cases. Each of the next T lines contains an integer N(1≤N≤10^9) indicating the number of blocks.

Output

For each test cases, output the number of ways to paint the blocks in a single line. Since the answer may be quite large, you have to module it by 10007.

Sample Input

2
1
2

Sample Output

2
6

Source


這道題是在《挑戰》裡面看到的一道題思路開始是真沒想到,理解思路之後自己推出了矩陣,感覺更加理解了矩陣構造(還只是簡單的矩陣。。。)

思路:通過題目中邏輯關係推出遞推式。根據題目中的“紅塊和綠塊的數量和都是偶數”分析得出遞推式。為了滿足題意就有了三種關係:1、紅綠都是偶數2、紅綠有一種

3、紅綠都是奇數

在這裡設ai表示從0到i紅塊和綠塊數量都是偶數,bi表示從0到i紅塊或者綠塊有一種的數量是偶數,ci表示從0到i紅塊和綠塊數量都是奇數

第i+1塊的顏色是受第i塊的影響的。為了在第i+1塊滿足題意就有了這三種情況對應的表示式:

ai+1 = 2ai + bi

bi+1 = 2ai + 2bi + 2ci

ci+1 = 2ci + bi

由此可以構造出矩陣

21 0

22 2

01 2

主要是構造矩陣,之後的可以套模板了

程式碼:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 5
#define cl(a,b) memset(a,b,sizeof(a))
const int mod = 10007;
using namespace std;
typedef long long ll;
int n, x;
struct matrix{
    ll a[maxn][maxn];
};
matrix multi(matrix x,matrix y){
    int i,j,k;
    matrix tmp;
    cl(tmp.a, 0);
    for (i=1;i<=n;i++){
        for (j=1;j<=n;j++)
        {
            if (!x.a[i][j]) continue;
            for (k=1;k<=n;k++)
            {
                tmp.a[i][k]+=x.a[i][j]*y.a[j][k];
                tmp.a[i][k]%=mod;
            }
        }
    }
    return tmp;
}
matrix power(matrix s,int p){
    int i;
    matrix res;
    cl(res.a, 0);
    for(i=1;i<=n;i++) res.a[i][i]=1;
    while (p){
        if (p&1) res=multi(res,s);
        p>>=1;
        s=multi(s,s);
    }
    return res;
}
int main(){
    int t;
    n = 3;
    matrix m;
    cl(m.a, 0);
	m.a[1][1] = 2;m.a[1][2] = 1;m.a[1][3] = 0;
	m.a[2][1] = 2;m.a[2][2] = 2;m.a[2][3] = 2;
    m.a[3][1] = 0;m.a[3][2] = 1;m.a[3][3] = 2;
    scanf("%d",&t);
    while (t--){
        scanf("%d",&x);
        matrix ans=power(m,x);
       /* cout<<"**************"<<endl;
        for(int i = 1; i <= 3; i++){
            for(int j = 1; j <= 3; j++)
                printf("%d ",ans.a[i][j]);
            printf("\n");
        }
        cout<<"**************"<<endl;*/
        printf("%d\n",ans.a[1][1]);
    }
    return 0;
}

ps:嘗試了vector的寫法,相對比較簡潔但是更加耗時。之前的kij優化方法沒有直接跳出快,這道題直接跳出空值的優化可以達到0MS(可能是題目的資料問題)

這題適合理解矩陣的構造,但是用其他方法可能更好一點(一般也不會直接想到用矩陣來解吧,,,),比如母函式就是一種。組合數學很強大的,可惜自己數學不強