首先将状态减半,奇数状态都为不合法状态,再将前31位状态打标,最后再对n按位累乘。
ACcode:
#include<cstdio>
#include<cstring>
typedef long long LL;
const int NS=8;
const int MS=1<<NS;
const int MSK=MS>>1;
const int MOD=1000000007;
struct matrix
{
int x[MSK][MSK];
}c[32],tmp;
int n,ok[MS];
LL x[MSK][MSK];
int match(int u,int v)
{
int flag=2;
for (int i=0;i<NS;i++)
{
if (u&(1<<i))
{
if (v&(1<<i))
{
if (i<NS-1&&(u&(1<<(i+1)))&&(v&(1<<(i+1)))) i++;
else {flag--;break;}
}
}
else if (!(v&(1<<i))) {flag--;break;}
}
u|=(u&1)<<NS,v|=(v&1)<<NS;
for (int i=NS;i>0;i--)
{
if (u&(1<<i))
{
if (v&(1<<i))
{
if (i>1&&(u&(1<<(i-1)))&&(v&(1<<(i-1)))) i--;
else {flag--;break;}
}
}
else if (!(v&(1<<i))) {flag--;break;}
}
flag=flag?1:0;
return flag;
}
matrix mul(matrix g,matrix h)
{
for (int i=0;i<MSK;i++)
for (int j=0;j<MSK;j++)
{
LL t=0;
for (int k=0;k<MSK;k++)
t+=((LL)g.x[i][k]*h.x[k][j])%MOD;
tmp.x[i][j]=t%MOD;
}
return tmp;
}
void prepare()
{
int t,dx=0,dy=0;
for (int i=0;i<MS;i++)
{
t=0;
for (int j=i;j>0;j=j&(j-1)) t++;
ok[i]=(t&1)^1;
}
for (int i=0;i<MS;i++)
if (ok[i])
{
dy=0;
for (int j=0;j<MS;j++)
if (ok[j]) x[dx][dy++]=match(i,j);
dx++;
}
x[MSK-1][MSK-1]++;
for (int i=0;i<MSK;i++)
for (int j=0;j<MSK;j++)
c[0].x[i][j]=x[i][j];
for (int i=1;i<32;i++)
c[i]=mul(c[i-1],c[i-1]);
}
int quick_pow(int y)
{
for (int i=0;i<MSK;i++)
for (int j=0;j<MSK;j++)
tmp.x[i][j]=i==j?1:0;
for (int i=0;i<32;i++)
if (y&(1<<i))
tmp=mul(tmp,c[i]);
return (int)tmp.x[MSK-1][MSK-1];
}
int main()
{
prepare();
int T,cas=0;
scanf("%d\n",&T);
while (~scanf("%d",&n))
printf("Case %d: %d\n",++cas,quick_pow(n));
return 0;
}