BNUOJ 3853 Blocks 矩阵快速幂

                    好吧,我应该不是第一次接触这种思想了,可是我以前做的题目都是显式的给出递推关系。。这样递推关系隐藏的还没有遇见过,也算是长长见识了。

                    总之要想办法转到矩阵上面来。为了方便称呼,我这里把四种颜色叫做a,b,c,d,而c,d就是题目特定要求的颜色。

                    然后考虑这三种状态: A(i)=格子数为i 块时c,d个数都是偶数的方法数

                                                             B(i)=格子数为i 块时c,d个数恰有一个是奇数的方法数

                                                             C(i)=格子数为i 块时c,d个数均为奇数的方法数

                    定义了这三个状态之后我们就可以开始递推了。

                                                             A(i+1)=2*A(i)+B(i)

                                                            B(i+1)=2*A(i)+2*B(i)+2*C(i)

                                                            C(i+1)=2*C(i)+B(i)

                  很眼熟是不是?马上发现就是线性代数里面的线性变换,马上上矩阵快速幂,此题就做完了。

#include<cstdio>
#include<cstring>

using namespace std;

const int modulu=10007;
int n,t;
int arr[3][3],muti[3][3],te[3][3];
void mul(int[3][3],int[3][3]);

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        if(n==1)
            printf("2\n");
        else{
            memset(arr,0,sizeof arr);
            arr[0][0]=arr[1][1]=arr[2][2]=1;
            memset(muti,0, sizeof muti);
            muti[0][0]=muti[1][0]=muti[1][1]=muti[1][2]=muti[2][2]=2;
            muti[0][1]=muti[2][1]=1;
            --n;
            while(n){
                if(n&1)
                    mul(arr,muti);
                mul(muti,muti);
                n>>=1;
            }
//            for(int i=0;i<3;++i){
//                for(int j=0;j<3;++j)
//                printf("%d ",arr[i][j]);
//                printf("\n");
//            }
            printf("%d\n",((arr[0][0]+arr[0][1])<<1)%modulu);
        }
    }
    return 0;
}

void mul(int a[3][3],int b[3][3]){
    memset(te,0,sizeof te);
    for(int i=0;i<3;++i)
    for(int j=0;j<3;++j)
    for(int k=0;k<3;++k)
    te[i][j]+=a[i][k]*b[k][j],te[i][j]%=modulu;

    for(int i=0;i<3;++i)
    for(int j=0;j<3;++j)
        a[i][j]=te[i][j];
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值