您的位置:首页 > 其它

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

2017-11-09 13:41 218 查看

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 long
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: