您的位置:首页 > 其它

POJ 3420 构造矩阵乘法

2012-04-01 08:48 330 查看
很有趣的题哈~很久以前看了matrix67大牛的相关博文,对这个题有点印象,但却不知道怎么做。

昨晚睡前构思了一下,还到老胡电脑上试敲,当然得出来的答案怪怪的。

一直记得是从0->0的方案,可是输出矩阵得出的却是15->15的方案....

下面说一下思路吧:

我们假定给出的4*N的瓷砖为

第N-2排放满有如下15种情况。0代表没有瓷砖,1代表有瓷砖

第N排     0000   0000   0000   0000     .......      0000     

第N-1排  0000   0001   0010   0011                 1111

下面我们把第N-1排放满,但是N-1排不能横着放,因为N-1排横着放会引起状态的重复。

好了,下面

第N排     0000  0001  0010  0011  ...... 1111

第N-1排  1111  1111  1111  1111        1111

具体状态是怎么转移的呢??

以0000 为例

   1110

在第N-1排竖着放一个-> 0001   再横着放一个  1101  0111

                                    1111                        1111  1111

这样由1110可以转变为3种状态。用二进制表示,可以得到一个状态转换图。

由1110到0001,1101,0111各有一条有向状态转换边。






这个状态矩阵转换N次幂的[1111][1111]就是求的摆法有多少种.....

Code:

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;

typedef __int64 ll;
struct node
{
ll ma[16][16];
};

node res,temp;
int N,M;
int bit[4];

void init(){
memset( res.ma,0,sizeof(res.ma) );
memset( temp.ma,0,sizeof(temp.ma) );
for( int i=0;i<16;i++ )
res.ma[i][i]=1;
for( int i=0;i<4;i++ )
bit[i]=(1<<i);
}
void set_matrix()
{
for( int i=0;i<16;i++ ){
temp.ma[i][(~i)&0xF]++;
for( int j=0;j<3;j++ )
if( ((~i)&bit[j]&0xF)==0 && ((~i)&bit[j+1]&0xF)==0 )
temp.ma[i][((~i)|bit[j]|bit[j+1])&0xF]++;
}
temp.ma[15][15]++;
}

node matriXmult( node a,node b )
{
node c;
memset( c.ma,0,sizeof(c.ma) );
for( int i=0;i<16;i++ )
for( int k=0;k<16;k++ )
if( a.ma[i][k] )
for( int j=0;j<16;j++ )
c.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
for( int i=0;i<16;i++ )
for( int j=0;j<16;j++ )
c.ma[i][j]%=M;
return c;
}

void matrix_Power()
{
for( int i=0;i<31;i++ )
{
if( N&(1<<i) )
res=matriXmult(res,temp);
temp=matriXmult(temp,temp);
}
}

int main()
{
while( scanf("%d%d",&N,&M)&&N|M )
{
init();
set_matrix();
matrix_Power();
printf( "%I64d\n",res.ma[15][15] );
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  matrix c