51nod 1122 机器人走方格 V4【组合数学】【矩阵乘法】

来源:互联网 发布:图片修复软件免费版 编辑:程序博客网 时间:2024/06/08 07:51

Description

四个机器人a b c d,在2 * 2的方格里,一开始四个机器人分别站在4个格子上,每一步机器人可以往临近的一个格子移动或留在原地(同一个格子可以有多个机器人停留),经过n步后有多少种不同的走法,使得每个毯子上都有1机器人停留。由于方法数量巨大,输出 Mod 10^9 + 7的结果。

题解

每个位置都是等价的,可以通过求解从第一个位置到另外的位置的方案数,然后枚举最后每个机器人的位置,利用乘法原理求总方案数。

首先给每个位置编号,从上到下,从左到右为0,1,2,3。定义f[i]表示从第0个位置到i的方案数,构造出转移矩阵,利用矩阵乘法加速DP。

代码

#include<cstdio>#include<cstring>#include<algorithm>#define tt 1000000007#define LL long longusing namespace std;const int flag[4][4]={{1,1,1,0},                      {1,1,0,1},                      {1,0,1,1},                      {0,1,1,1}};struct matrix{    int n,m,a[4][4];    matrix operator *(const matrix b){        matrix c;        c.n=n;c.m=b.m;        memset(c.a,0,sizeof(c.a));        for(int i=0;i<n;i++)         for(int j=0;j<b.m;j++)          for(int k=0;k<m;k++) (c.a[i][j]+=(LL)a[i][k]*b.a[k][j]%tt)%=tt;        return c;    }}A,ans;int n;LL anss;bool vis[4];matrix power(matrix x,int y){    matrix w=x,sum;    memset(sum.a,0,sizeof(sum.a));    sum.n=sum.m=4;    for(int i=0;i<4;i++)sum.a[i][i]=1;    while(y){        if(y&1)sum=sum*w;        y>>=1;w=w*w;    }    return sum;}int main(){    freopen("machinrium.in","r",stdin);    freopen("machinrium.out","w",stdout);    scanf("%d",&n);    A.n=A.m=4;memcpy(A.a,flag,sizeof(flag));    ans.n=1;ans.m=4;ans.a[0][1]=1;    ans=ans*power(A,n);    for(int i=0;i<4;i++)     for(int j=0;j<4;j++)      for(int k=0;k<4;k++)       for(int t=0;t<4;t++){        memset(vis,1,sizeof(vis));        vis[i%4]=0;if(!vis[(1+j)%4])continue;        vis[(1+j)%4]=0;if(!vis[(2+k)%4])continue;        vis[(2+k)%4]=0;if(!vis[(3+t)%4])continue;        (anss+=(LL)ans.a[0][i]*ans.a[0][j]%tt*ans.a[0][k]%tt*ans.a[0][t]%tt)%=tt;       }    printf("%lld\n",anss);    return 0;}
原创粉丝点击