zoj 3256 Tour in the Castle

这题是poj1739的改编版,在那份题解里我用了两种写法,这题的m很大,显然快速幂,BFS所有状态,不过矩阵也相当的大,我算了最大状态是114这么多,所以我优化了快速幂,预存幂矩阵,然后n^2快速幂,跑了600+,那个第一的200+ms是有减少状态么,还是有其他优化方法,我被他时间空间完胜了,Orz。

Run IDSubmit TimeJudge StatusProblem IDLanguageRun Time(ms)Run Memory(KB)User Name
30719912012-10-02 17:29:15Accepted3256C++67013012xym

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
const int maxn=10001,mod=7777777;
int mov[10]={0,2,4,6,8,10,12,14,16},mp[2<<16],res[130],tem[130],pos;
bool vd[2<<16];
int A[6][30][130][130]={0},B[130][130],len[6],sp[6][2];
struct node
{
	int size,head[maxn],next[maxn],sta[maxn];
	inline void clear()
	{
		memset(head,-1,sizeof(head));
		size=0;
	}
	inline void push(int st)
	{
		int hash=st%maxn;
		for(int i=head[hash];i>=0;i=next[i])
		{
			if(sta[i]==st)
				return;
		}
		sta[size]=st,next[size]=hash;
		head[hash]=size++;
	}
}dp[2];
inline int getbit(int st,int k){return 3&(st>>mov[k]);}
inline int pybit(int st,int k){return st<<mov[k];}
inline int clrbit(int st,int a,int b){return st&(~(3<<mov[a]))&(~(3<<mov[b]));}
inline int fl(int st,int k,int n)
{
	int cnt=1;
	for(int i=k+1;i<=n;i++)
	{
		int e=getbit(st,i);
		if(e==2) cnt--;
		else if(e==1) cnt++;
		if(cnt==0)
			return i;
	}
}
inline int fr(int st,int k)
{
	int cnt=1;
	for(int i=k-1;i>=0;i--)
	{
		int e=getbit(st,i);
		if(e==2) cnt++;
		else if(e==1) cnt--;
		if(cnt==0)
			return i;
	}
}
inline int find(int st)
{
	if(mp[st]==-1)
		mp[st]=pos++;
	return mp[st];
}
void bfs(int n)
{
	int in,out;
	queue<int >q;
	memset(vd,0,sizeof(vd));
	memset(mp,-1,sizeof(mp));
	memset(B,0,sizeof(B));
	pos=0;
	in=pybit(1,0)+pybit(2,n-1);
	vd[in]=1,q.push(in);
	while(!q.empty())
	{
		out=q.front();
		q.pop();
		dp[0].clear();
		dp[0].push(out<<2);
		int now=0,pre=1;
		for(int j=1;j<=n;j++)
		{
			pre=now,now^=1;dp[now].clear();
			for(int k=0;k<dp[pre].size;k++)
			{
				int l=getbit(dp[pre].sta[k],j-1);
				int up=getbit(dp[pre].sta[k],j);
				int st=clrbit(dp[pre].sta[k],j-1,j);
				if(!l&&!up)
				{
					if(j<n)
					dp[now].push(st|pybit(1,j-1)|pybit(2,j));
				}
				else if(!l||!up)
				{
					int e=l==0?up:l;
					dp[now].push(st|pybit(e,j-1));
					if(j<n)
						dp[now].push(st|pybit(e,j));
				}
				else if(l==1&&up==1)
					dp[now].push(st^pybit(3,fl(st,j,n)));
				else if(l==2&&up==2)
					dp[now].push(st^pybit(3,fr(st,j-1)));
				else if(l==2&&up==1)
					dp[now].push(st);
				else if(j==n&&st==0)
					B[find(out)][find(st)]++;

			}
		}
		for(int j=0;j<dp[now].size;j++)
		{
			in=dp[now].sta[j];
			if(!vd[in])
			{
				vd[in]=1;
				q.push(in);
			}
			B[find(out)][find(in)]++;
		}
	}
	//printf("%d\n",pos);
}
void init()
{
	for(int i=0;i<=5;i++)
	{
		bfs(i+2);
		len[i]=pos;
		sp[i][0]=find(pybit(1,0)+pybit(2,i+1));
		sp[i][1]=find(0);
		for(int j=0;j<len[i];j++)
			for(int k=0;k<len[i];k++)
				A[i][0][j][k]=B[j][k];
		for(int j=1;j<30;j++)
		{
			for(int x=0;x<len[i];x++)
				for(int y=0;y<len[i];y++)
				{
					for(int z=0;z<len[i];z++)
					{
						LL t=(LL)(A[i][j-1][x][z]*(LL)A[i][j-1][z][y]);
						if(t>=mod)t%=mod;
						A[i][j][x][y]+=t;
						if(A[i][j][x][y]>=mod)  A[i][j][x][y]-=mod;
					}
				}
		}
	}
}
void q_exp(int k,int e)
{
	int cnt=0;
	while(k)
	{
		if(k&1)
		{
			for(int j=0;j<len[e];j++)
			{
				tem[j]=0;
				for(int k=0;k<len[e];k++)
				{
					LL t=(LL)res[k]*(LL)A[e][cnt][k][j];
					if(t>=mod)t%=mod;
					tem[j]+=t;
					if(tem[j]>=mod)tem[j]-=mod;
				}
			}	
			memcpy(res,tem,sizeof(tem));
		}
		k>>=1;
		cnt++;
	}
}
int n,m;
int main()
{	
	init();
	while(~scanf("%d%d",&n,&m))
	{
		memset(res,0,sizeof(res));
		res[sp[n-2][0]]=1;
		q_exp(m,n-2);
		if(res[sp[n-2][1]]==0)
			puts("Impossible");
		else
		cout<<res[sp[n-2][1]]<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值