随笔-14  评论-21  文章-0  trackbacks-0

矩阵乘法是显然的
把末2位的状态分成4类:
S1:黑黑、红红、蓝蓝
S2:黑红、黑蓝、红黑、红蓝、蓝黑、蓝红
S3:白白、黑白、蓝白、红白
S4:白黑、白红、白蓝

则有
S'1=S4
S'2=S2+2S4
S'3=S1+S2+S3+S4
S'4=3S3

得到矩阵A
0 0 1 0
0 1 1 0
0 0 1 3
1 2 1 0


直接做矩阵乘法居然超时,时限太BT了,所以我把要求的二进制数拆成三部分,预处理求出以下值

A0,A1,...,A1023
A0,A1024,...,A1047552
A0,A1048576,...,A1072693248

然后对于每个询问,只用求三个矩阵的乘积即可

#include <iostream>
#include 
<cstdlib>
#include 
<cstdio>

using namespace std;

const int mo=1000000007;
const int c[4][4]={{0,0,1,0},
                   {
0,1,1,0},
                   {
0,0,1,3},
                   {
1,2,1,0}};
const int e[4][4]={{1,0,0,0},
                   {
0,1,0,0},
                   {
0,0,1,0},
                   {
0,0,0,1}};
const int s[4]={3,6,4,3};

char st[20];

int f[32][4][4],res1[1024][4][4],res2[1024][4][4],res3[1024][4][4],a[4][4],b[4][4];

void multi(int a[4][4],int b[4][4],int c[4][4])
{
  
int i,j,k;
  
long long tmp;
  
for(i=0;i<4;i++)
    
for(j=0;j<4;j++)
    {
      tmp
=0;
      
for(k=0;k<4;k++)
        tmp
+=(long long)(a[i][k])*b[k][j];
      c[i][j]
=tmp%mo;
    }
}

int getint(void)
{
  gets(st);
  
int res=0;
  
for(int i=0;st[i]!='\0';i++)
    
if(st[i]>='0'&&st[i]<='9')
      res
=res*10+st[i]-48;
  
return res;
}

int main(void)
{
  
int k,i,j,u,n,ans;
  
long long tmp;
  
for(i=0;i<4;i++)
    
for(j=0;j<4;j++)
    {
      f[
0][i][j]=c[i][j];
      res1[
0][i][j]=res2[0][i][j]=res3[0][i][j]=e[i][j];
    }
  
for(k=1;k<=20;k++)
    multi(f[k
-1],f[k-1],f[k]);
  
for(k=1;k<1024;k++)
    multi(res1[k
-1],f[0],res1[k]);
  
for(k=1;k<1024;k++)
    multi(res2[k
-1],f[10],res2[k]);
  
for(k=1;k<1024;k++)
    multi(res3[k
-1],f[20],res3[k]);
  u
=getint();
  
while(u--)
  {
    n
=getint();
    
if (n==1)
    {
      printf(
"%d\n",4);
      
continue;
    }
    n
-=2;
    multi(res1[n
&1023],res2[(n>>10)&1023],b);
    multi(b,res3[(n
>>20)&1023],a);
    tmp
=0;
    
for(i=0;i<4;i++)
      
for(j=0;j<4;j++)
        tmp
+=(long long)(s[i])*a[i][j];
    ans
=tmp%mo;
    printf(
"%d\n",ans);
  }
  
return 0;
}


 

posted on 2010-10-01 23:50 zxb 阅读(183) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理