【poj3734】矩阵乘法

题解:

若当前有i个格子。
2个是偶数的方案数为a[i]
1个是偶数的方案数为b[i]
0个是偶数的方案数为c[i]

a[i+1]=2*a[i](i+1染成黄或蓝)+b[i](把奇数变为偶数)
b[i+1]=2*a[i](把某个偶数变为奇数)+2*b[i](i+1染成黄或蓝)+2*c[i](把某个奇数变为偶数)
c[i+1]=b[i](把偶数变为奇数)+2*c[i](i+1染成黄或蓝)

解析式难想,要学会这种分类递推的方法。

然后就可以推出

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

const int N=1000000010,Mod=10007;

struct node{
    int sx,sy;
    int s[4][4];
};

node mult(node a,node b)
{
    node c;
    c.sx=a.sx;c.sy=b.sy;
    memset(c.s,0,sizeof(c.s));
    for(int i=1;i<=a.sx;i++)
        for(int j=1;j<=b.sy;j++)
            for(int k=1;k<=a.sx;k++)
            {
                c.s[i][j]+=(a.s[i][k]*b.s[k][j])%Mod;
                c.s[i][j]%=Mod;
            }
    return c;
}

void solve(int x)
{
    node a;
    a.sx=a.sy=3;
    a.s[1][1]=2;a.s[1][2]=1;a.s[1][3]=0;
    a.s[2][1]=a.s[2][2]=a.s[2][3]=2;
    a.s[3][1]=0;a.s[3][2]=1;a.s[3][3]=2;
    node b;
    b.sx=b.sy=3;
    memset(b.s,0,sizeof(b.s));
    for(int i=1;i<=3;i++) b.s[i][i]=1;
    while(x)
    {
        if(x&1) b=mult(b,a);
        a=mult(a,a);
        x>>=1;
    }
    node c;
    c.sx=3;c.sy=1;
    c.s[1][1]=1;
    c.s[2][1]=c.s[3][1]=0;
    c=mult(b,c);
    
    printf("%d
",c.s[1][1]);
    return ;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int x;
        scanf("%d",&x);
        solve(x);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/KonjakJuruo/p/4820856.html