51nod 1122 機器人走方格 V4【組合數學】【矩陣乘法】

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;
}
發佈了143 篇原創文章 · 獲贊 18 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章