标签:io os sp for on 代码 amp ef as
题意:
给长度N的格子,有六种颜料ABCDEF,
要求涂满N个格子的方案数,并且保证是对称的,并且相邻的格子颜色不同,并且不出现ABCDEF这个序列。
思路:
受到中午那题,思维大开
首先因为颜色相邻不能相同且要对称,所以N为偶数答案为0.
接着先假设有这六种状态0(代表没颜色限制),A,AB,ABC,ABCD,ABCDE
然后初始状态为(5,1,0,0,0,0)两两之间构成转换关系
结果提交WA了
发现这题真是丧心病狂
如果是这样FEDCBABCDEF 这样对称的话就会跪
所以还有5个状态 F,FE,FED,FEDC,FEDCB
总共11个状态互相转换
注意之间的转换关系就好了
所以初始的是(4,1,0,0,0,0,1,0,0,0,0)
转换矩阵是
3 1 0 0 0 0 1 0 0 0 0
3 0 1 0 0 0 1 0 0 0 0
2 1 0 1 0 0 1 0 0 0 0
2 1 0 0 1 0 1 0 0 0 0
2 1 0 0 0 1 1 0 0 0 0
3 1 0 0 0 0 0 0 0 0 0
3 1 0 0 0 0 0 1 0 0 0
2 1 0 0 0 0 1 0 1 0 0
2 1 0 0 0 0 1 0 0 1 0
2 1 0 0 0 0 1 0 0 0 1
3 0 0 0 0 0 1 0 0 0 0
然后最后ans.mat[0][0~10]求和一下就是答案啊了~!
代码:
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
__int64 mod=112233;
struct matrix
{
__int64 mat[13][13];
};
matrix matmul(matrix a,matrix b,int n,__int64 m)
{
int i,j,k;
matrix c;
memset(c.mat,0,sizeof(c.mat));
for(i=0; i<n; i++)
{
for(k=0; k<n; k++)
{
for(j=0; j<n; j++)
{
c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
c.mat[i][j]%=m;
}
}
}
return c;
}
matrix matpow(matrix a,__int64 k,int n,__int64 m)
{
matrix b;
int i;
memset(b.mat,0,sizeof(b.mat));
for(i=0; i<n; i++) b.mat[i][i]=1;
while(k)
{
if(k&1) b=matmul(a,b,n,m);
a=matmul(a,a,n,m);
k>>=1;
}
return b;
}
int main()
{
__int64 n;
while(scanf("%I64d",&n)!=-1)
{
if(n%2==0)
{
puts("0");
continue;
}
matrix a,b,ans;
memset(a.mat,0,sizeof(a.mat));
memset(b.mat,0,sizeof(b.mat));
a.mat[0][0]=4;
a.mat[0][1]=a.mat[0][6]=1;
b.mat[0][0]=b.mat[1][0]=b.mat[5][0]=b.mat[6][0]=b.mat[10][0]=3;
for(int i=0;i<11;i++)
{
if(b.mat[i][0]==0) b.mat[i][0]=2;
}
for(int i=0;i<10;i++) b.mat[i][i+1]=1;
for(int i=2;i<10;i++) b.mat[i][1]=1;
for(int i=0;i<11;i++)
{
if(i!=6) b.mat[i][6]=1;
}
b.mat[5][6]=0;
ans=matmul(a,matpow(b,n/2,11,mod),11,mod);
__int64 sum=0;
for(int i=0;i<11;i++) sum=(sum+ans.mat[0][i])%mod;
printf("%I64d\n",sum);
}
return 0;
}
[矩阵快速幂] hdu 3893 Drawing Pictures
标签:io os sp for on 代码 amp ef as
原文地址:http://blog.csdn.net/wdcjdtc/article/details/41259475