记录编号 218766 评测结果 AAAAAAAAAA
题目名称 [HNOI 2004] 邮递员 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 0.048 s
提交时间 2016-01-11 11:11:13 内存使用 0.43 MiB
显示代码纯文本
#define ll long long

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

const int Base=(int)(1e9);
int n,m;

inline int Max(int a,int b){return a>b?a:b;}

struct BigNum{
	#define MAXSIZE 5UL
	int s[MAXSIZE];
	BigNum(){clr();return;}
	inline void clr(){memset(s,0,sizeof(s));return;}
	inline void setnum(int x){clr();while(x) s[++s[0]]=x%Base,x/=Base;return;}
	inline void prx(){printf("%d",s[s[0]]);for(int i=s[0]-1;i>0;i--) printf("%09d",s[i]);return;}
	friend BigNum operator + (BigNum temp_a,BigNum temp_b){
		BigNum temp_c;int *a=temp_a.s,*b=temp_b.s,*c=temp_c.s;int i;
		for(c[0]=Max(a[0],b[0])+1,i=1;i<=c[0];i++) c[i]+=a[i]+b[i],c[i+1]+=c[i]/Base,c[i]%=Base;
		while(!c[c[0]]) --c[0];return temp_c;
	}
	void operator += (BigNum b){*this=*this+b;return;}
	void operator = (int t){setnum(t);return;}
}Ans;

struct HashTable{
	#define MAXHASH 2601L
	int key[MAXHASH];int cnt,hash[MAXHASH];BigNum val[MAXHASH];
	inline void clr(){cnt=0;memset(key,-1,sizeof(key));memset(hash,0,sizeof(hash));memset(val,0,sizeof(val));return;}
	inline void NewNode(int i,int key_){hash[i]=++cnt;key[cnt]=key_;return;}
	BigNum& operator [] (const int hash_){
		int k;
		for(int i=hash_%MAXHASH;;i++){
			if(i==MAXHASH) i=0;
			if(!hash[i]) NewNode(i,hash_);
			if(key[hash[i]]==hash_){k=hash[i];break;}
		}
		return val[k];
	}
}f[2];

inline void Change(int &t,int c,int r){int w=(c-1)<<1;t|=3<<w;t^=3<<w;t|=r<<w;return;}
inline int Get(int t,int c){return (t>>((c-1)<<1))&3;}
inline int Find(int t,int c){for(int i=c,b=0,rep=Get(t,c)==1?1:-1;;i+=rep){b+=Get(t,i)==1?1:-1;b+=Get(t,i)==0?1:0;if(b==0) return i;}return -1;}

inline void DP(int i,int j){
	int now=((i-1)*m+j)&1,last=now^1,tot=f[last].cnt;f[now].clr();
	for(int x=1,p,q;x<=tot;x++){
		int t=f[last].key[x];
		BigNum val=f[last].val[x];
		p=Get(t,j),q=Get(t,j+1);
		if(p==0&&q==0){if(i==n||j==m) continue;Change(t,j,1);Change(t,j+1,2);f[now][t]+=val;}
		else if(p>0&&q==0){if(i!=n) f[now][t]+=val;if(j!=m) Change(t,j,0),Change(t,j+1,p),f[now][t]+=val;}
		else if(p==0&&q>0){if(j!=m) f[now][t]+=val;if(i!=n) Change(t,j,q),Change(t,j+1,0),f[now][t]+=val;}
		else if(p==1&&q==1){Change(t,Find(t,j+1),1);Change(t,j,0);Change(t,j+1,0);f[now][t]+=val;}
		else if(p==2&&q==2){Change(t,Find(t,j),2);Change(t,j,0);Change(t,j+1,0);f[now][t]+=val;}
		else if(p==1&&q==2){if(i==n&&j==m) Ans+=val;}
		else if(p==2&&q==1){Change(t,j,0);Change(t,j+1,0);f[now][t]+=val;}
	}
	return;
}

int main(){
	freopen("postman.in","r",stdin);freopen("postman.out","w",stdout);
	scanf("%d%d",&n,&m);
	if(n==1||m==1){puts("1");return 0;}
	if(n<m) n^=m,m^=n,n^=m;
	f[0].clr();f[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) DP(i,j);
		if(i!=n) for(int k=1,R=f[(i*m)&1].cnt,c=(i*m)&1;k<=R;k++) f[c].key[k]<<=2;
	}
	Ans+=Ans;Ans.prx();
	return 0;
}