您的位置:首页 > 其它

ZOJ 3256 Tour in the Castle

2014-05-13 15:46 190 查看
求环路的个数,按照列来DP转移。

由于M比较大所以需要矩阵乘法+快速幂。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>

using namespace std;

const int STATE=1010;
const int HASH=419;//这个小一点,效率高
const int MOD=7777777;

int N,M;
int D;
int code[10];
int ch[10];
int g[200][200];//状态转移图

struct Mat{
int n,m;
int mat[200][200];
};

Mat mul(Mat a,Mat b)//矩阵相乘,要保证a的列数和b的行数相等
{
Mat ret;
ret.n=a.n;
ret.m=b.m;
long long sum;
for(int i=0;i<a.n;i++)
for(int j=0;j<b.m;j++)
{
sum=0;
for(int k=0;k<a.m;k++)
{
sum+=(long long)a.mat[i][k]*b.mat[k][j];
}
ret.mat[i][j]=sum%MOD;
}
return ret;
}

Mat pow_mod(Mat a,int n)//方阵的n次方
{
Mat ret=a;
memset(ret.mat,0,sizeof(ret.mat));
for(int i=0;i<a.n;i++)ret.mat[i][i]=1;//单位阵
Mat temp=a;
while(n)
{
if(n&1)ret=mul(ret,temp);
temp=mul(temp,temp);
n>>=1;
}
return ret;
}

struct HASHMAP
{
int head[HASH],next[STATE],size;
int state[STATE];
void init()
{
size=0;
memset(head,-1,sizeof(head));
}
int push(int st)
{
int i,h=st%HASH;
for(i=head[h];i!=-1;i=next[i])
if(state[i]==st)
return i;
state[size]=st;
next[size]=head[h];
head[h]=size++;
return size-1;
}
}hm;

void decode(int *code,int n,int st)
{
for(int i=n-1;i>=0;i--)
{
code[i]=st&3;
st>>=2;
}
}

int encode(int *code,int n)
{
int cnt=1;
memset(ch,-1,sizeof(ch));
ch[0]=0;
int st=0;
for(int i=0;i<n;i++)
{
if(ch[code[i]]==-1)ch[code[i]]=cnt++;
code[i]=ch[code[i]];
st<<=2;
st|=code[i];
}
return st;
}

bool check(int st,int nst)//判断两种状态能不能转移
{
decode(code,N,st);
int flag=0;//标记格子上边是否有插头
int cnt=0;
int k;
for(int i=0;i<N;i++)
{
if(flag==0)//这个格子上边没有插头
{
if(code[i]==0&&(nst&(1<<i))==0)//左边和右边都没有插头
return false;
if(code[i]&&(nst&(1<<i)))continue;
if(code[i])flag=code[i];//插头从左边过来,从下边出去
else flag=-1;//插头从下边进来从右边出去
k=i;
}
else
{
if(code[i]&&(nst&(1<<i)))//左边和右边和上边都有插头
return false;
if(code[i]==0&&(nst&(1<<i))==0)continue;
if(code[i])
{
if(code[i]==flag&&((nst!=0)||i!=N-1))return false;//只有最后一个格子才能合起来
if(flag>0)
{
for(int j=0;j<N;j++)
if(code[j]==code[i]&&j!=i)
code[j]=code[k];
code[i]=code[k]=0;
}
else
{
code[k]=code[i];
code[i]=0;
}
}
else
{
if(flag>0)code[i]=code[k],code[k]=0;
else code[i]=code[k]=N+(cnt++);
}
flag=0;
}
}
if(flag!=0)return false;
return true;
}

struct Node
{
int g[200][200];
int D;
}node[20];//打表之用

void init()
{
if(node
.D!=0)
{
memcpy(g,node
.g,sizeof(node
.g));
D=node
.D;
return;
}
int st,nst;
hm.init();
memset(code,0,sizeof(code));
code[0]=code[N-1]=1;
hm.push(0);
hm.push(encode(code,N));
memset(g,0,sizeof(g));
for(int i=1;i<hm.size;i++)
{
st=hm.state[i];
for(nst=0;nst<(1<<N);nst++)
if(check(st,nst))
{
int j=hm.push(encode(code,N));
g[i][j]=1;
}
}
D=hm.size;
memcpy(node
.g,g,sizeof(g));
node
.D=D;
}

void solve()
{
Mat temp;
temp.n=temp.m=D;
memcpy(temp.mat,g,sizeof(g));
Mat ans=pow_mod(temp,M);
if(ans.mat[1][0]==0)printf("Impossible\n");
else printf("%d\n",ans.mat[1][0]%MOD);
}

int main()
{
/*freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);*/
for(int i=0;i<20;i++)node[i].D=0;
while(scanf("%d%d",&N,&M)==2)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: