POJ 3734


题目大意:

        给定待粉刷的n个墙砖(排成一行),每个墙砖可以粉刷的颜色种类为:红、蓝、绿、黄,问粉刷完毕后,红色墙砖和蓝色墙砖都是偶数的粉刷方式有多少种(结果对10007取余).


解题思路:


       思路用的是递推.假设粉刷到第i个墙砖时,使用的红色墙砖和蓝色墙砖都是偶数的方案数有ai,使用的红色和蓝色墙砖一奇一偶的方案数为bi,使用的红色和蓝色墙砖都是奇数的方案数为ci,那么,我们容易得到下面的递推式:



        看到上式,对于学过线代的人来说一定不陌生,我们可以将其写成矩阵的形式,然后会发现该递推式是等比数列的形式.




        对于求取,我们可通过计算相应矩阵的幂得知,计算矩阵的幂,利用快速二分幂,可将时间复杂度降为.


解题代码:


#include<vector>
#include<iostream>
#include<algorithm>
#define M 10007
using namespace std;
//矩阵乘法
vector<vector<int> > multi(vector<vector<int> > &A, vector<vector<int> > &B)
{
    vector<vector<int> > C(A.size(), vector<int>(B[0].size()));
    for (unsigned i = 0; i != A.size(); ++i)
        for (unsigned j = 0; j != B[0].size(); ++j)
            for (unsigned k = 0; k != B.size(); ++k)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % M;
    return C;
}
//二分快速幂
vector<vector<int> > power(vector<vector<int> > &A, int n)
{
    vector<vector<int> > B(A.size(), vector<int>(A.size()));
    for (int i = 0; i != A.size(); ++i)
        B[i][i] = 1;
    while (n)
    {
        if (n & 1)
            B = multi(B, A);
        A = multi(A, A), n >>= 1;
    }
    return B;
}
int main()
{
    int t,n;
    cin >> t;
    while (t--)
    {
        vector<vector<int> > A(3, vector<int>(3));
        A[0][0] = 2, A[0][1] = 1, A[0][2] = 0;
        A[1][0] = 2, A[1][1] = 2, A[1][2] = 2;
        A[2][0] = 0, A[2][1] = 1, A[2][2] = 2;
        cin >> n;
        A = power(A, n);
        cout << A[0][0] << endl;
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值