POJ 3734 Blocks

本文介绍了一种使用矩阵快速幂解决特定组合计数问题的方法。通过定义三个状态A、B、C来表示不同条件下方案的数量,并推导出状态转移矩阵,最终通过快速幂求得第n项的值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目描述:点击打开链接

2.解题思路:本题利用矩阵快速幂解决。不妨设Ai表示前i个元素中,红绿均为偶数的方案数;Bi表示前i个中,红绿一奇一偶的方案数;Ci表示前i个方块中,红绿均为奇数的方案数。这样,可以得到如下3个递推式。

A[i+1]=2*A[i]+B[i];

B[i+1]=2*A[i]+2*B[i]+2*C[i];

C[i+1]=B[i]+2*C[i];

将表达式写成矩阵形式,然后自乘n次后,第(0,0)项就是答案。

3.代码:

#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define me(s)  memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;

const int MOD=10007;
struct Matrix
{
    int m[3][3];
    Matrix(){me(m);}
    void clear(){me(m);}
    void getE()
    {
        me(m);
        for(int i=0;i<3;i++)
            m[i][i]=1;
    }
    Matrix operator*(const Matrix&B)const
    {
        Matrix res;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            for(int k=0;k<3;k++)
            res.m[i][j]=(res.m[i][j]+m[i][k]*B.m[k][j])%MOD;
        return res;
    }
    Matrix operator^(int d)
    {
        Matrix res,B=*this;
        res.getE();
        while(d>0)
        {
            if(d&1)res=res*B;
            B=B*B;
            d>>=1;
        }
        return res;
    }
    Matrix out()
    {
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            printf("%d%c",m[i][j]," \n"[j==2]);
    }
};

Matrix A;

void init()
{
    A.m[0][0]=2,A.m[0][1]=1,A.m[0][2]=0;
    A.m[1][0]=2,A.m[1][1]=2,A.m[1][2]=2;
    A.m[2][0]=0,A.m[2][1]=1,A.m[2][2]=2;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        int d;
        scanf("%d",&d);
        A=A^d;
        printf("%d\n",A.m[0][0]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值