poj-3734(矩阵快速幂+推导)

问题描述:

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

题目题意:题目给我们四种颜色(红,绿,蓝,黄),总共有N块板子,我们要用那四种颜色,来涂板子,要求红色和绿色的板子必须是偶数个(可以为0)问有多少种涂色的方法?

题目分析:当时做的时候,也是想在过程上找到突破,但是想了半天也没什么好的思路,后来,我们在结果上找突破,被我旁边的大神看出了规律;

f(n)=4*f(n-1)-2^(n-1);

这个规律是直接在答案上构造的,有一定的巧合性.

我们构造如下矩阵:

 4  0  -4           f(n-1)          f(n)

 0  4  -2  *        f(n-2)  =     f(n-1)

 0  0   2            1                 2

这个矩阵构造的很特殊,可能你会发现,这个不一定成立(的确,这个矩阵只符合n为3时),但是矩阵的最后一行就是控制2^(n-1) 这个变量的,所以矩阵也在改变,符合每一个n


代码如下:

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

const int mod=10007;
struct matrix
{
    int f[4][4];
    matrix operator * ( matrix &a) {
        matrix res;
        for (int i=1;i<=3;i++) {
            for (int j=1;j<=3;j++) {
                res.f[i][j]=0;
                for (int k=1;k<=3;k++)
                    res.f[i][j]+=(f[i][k]*a.f[k][j])%mod;
                res.f[i][j]=(res.f[i][j]%mod+mod)%mod;//防止负数了
            }
        }
        return res;
    }
}a,b;

void init()
{
    b.f[1][1]=4,b.f[1][3]=-4;
    b.f[2][2]=4,b.f[2][3]=-2;
    b.f[3][3]=2;
    a.f[1][1]=6,a.f[2][1]=2,a.f[3][1]=1;
}

matrix fast_pow(matrix base,int k)
{
    matrix ans=b;
    while (k) {
        if (k&1)
          ans=ans*base;
        base=base*base;
        k>>=1;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while (t--) {
        int n;
        scanf("%d",&n);
        if (n==1) { printf("%d\n",2); continue;}
        if (n==2) { printf("%d\n",6); continue;}
        init();
        n-=3;
        matrix cur,ans;
        cur=b;
        cur=fast_pow(cur,n);
        ans=cur*a;
        printf("%d\n",ans.f[1][1]%mod);
    }
    return 0;
}













































以下是Java解决POJ3233—矩阵幂序列问题的代码和解释: ```java import java.util.Scanner; public class Main { static int n, k, m; static int[][] A, E; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); k = sc.nextInt(); m = sc.nextInt(); A = new int[n][n]; E = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { A[i][j] = sc.nextInt() % m; E[i][j] = (i == j) ? 1 : 0; } } int[][] res = matrixPow(A, k); int[][] ans = matrixAdd(res, E); printMatrix(ans); } // 矩阵乘法 public static int[][] matrixMul(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % m; } } } return c; } // 矩阵快速幂 public static int[][] matrixPow(int[][] a, int b) { int[][] res = E; while (b > 0) { if ((b & 1) == 1) { res = matrixMul(res, a); } a = matrixMul(a, a); b >>= 1; } return res; } // 矩阵加法 public static int[][] matrixAdd(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = (a[i][j] + b[i][j]) % m; } } return c; } // 输出矩阵 public static void printMatrix(int[][] a) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } } ``` 解释: 1. 首先读入输入的n、k、m和矩阵A,同时初始化单位矩阵E。 2. 然后调用matrixPow函数求出A的k次幂矩阵res。 3. 最后将res和E相加得到结果ans,并输出。 4. matrixMul函数实现矩阵乘法,matrixPow函数实现矩阵快速幂,matrixAdd函数实现矩阵加法,printMatrix函数实现输出矩阵。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值