题目
求网格图哈密顿回路个数,和模板提相差不大。
分析
和模板提的差别只在 (int128) 和乘以2以及特判。
代码
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define int __int128
#define ll __int128
#define PII pair<int,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ull unsigned long long
const int N=2e6+5,M=30,K=3005,INF=1e9+7,MOD=2991;
struct state{int a[M];};
int n,m,now,lst,edi,edj;
ll Ans,val[N<<1],to[N<<1];
int head[K],nex[N<<1],idx[2];
struct Node{int nex,to[2];ll val[2];}s[N];
inline void Insert(int x,ll v){
int key=x%MOD;
for(int i=head[key];i;i=s[i].nex) if(s[i].to[now]==x) return s[i].val[now]+=v,void();
s[++idx[now]].nex=head[key];
s[idx[now]].to[now]=x;
s[idx[now]].val[now]=v;
head[key]=idx[now];
return ;
}
inline state Unpack(ll x){
state S;S.a[0]=x&3;
for(ll i=1;i<=m;i++) S.a[i]=((x>>(i<<1))&3);
return S;
}
inline ll Judge(state S){
int res=0;res|=S.a[0];
for(ll i=1;i<=m;i++) res|=(S.a[i]<<(i<<1));
return res;
}
char str[M];
bool vis[M][M];
void DP(){
Insert(0,1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
lst=now,now^=1;memset(head,0,sizeof(head));idx[now]=0;
for(int k=1;k<=idx[lst];k++){
state tmp=Unpack(s[k].to[lst]),las=tmp;
ll num=s[k].val[lst];int west=las.a[0],north=las.a[j];
if(!vis[i][j]){
if(!west&&!north) Insert(Judge(las),num);
continue;
}
if(!west&&!north){
if(vis[i+1][j]&&vis[i][j+1]){
las.a[0]=2,las.a[j]=1;
Insert(Judge(las),num);
las=tmp;
}
continue;
}
if(!west&&north){
if(vis[i+1][j]) Insert(Judge(las),num);
if(vis[i][j+1]){
las.a[j]=0,las.a[0]=north;
Insert(Judge(las),num);
las=tmp;
}
continue;
}
if(west&&!north){
if(vis[i][j+1]) Insert(Judge(las),num);
if(vis[i+1][j]){
las.a[j]=west,las.a[0]=0;
Insert(Judge(las),num);
las=tmp;
}
continue;
}
if(west==1&&north==1){
int pos,res=1;
for(pos=j+1;pos<=m;pos++){
res+=las.a[pos]==1?1:las.a[pos]==2?-1:0;
if(res==0) break;
}
las.a[pos]=1,las.a[0]=las.a[j]=0;
Insert(Judge(las),num);las=tmp;
continue;
}
if(west==2&&north==2){
int pos,res=-1;
for(pos=j-1;pos;pos--){
res+=las.a[pos]==1?1:las.a[pos]==2?-1:0;
if(res==0) break;
}
las.a[pos]=2,las.a[0]=las.a[j]=0;
Insert(Judge(las),num);las=tmp;
continue;
}
if(west==2&&north==1){
las.a[0]=las.a[j]=0;
Insert(Judge(las),num);
las=tmp;
continue;
}
if(west==1&&north==2){
bool fl=0;
las.a[0]=las.a[j]=0;
for(int pos=0;pos<=m;pos++){if(las.a[pos]){fl=true;break;}}
if(!fl&&i==edi&&j==edj) Ans+=num;
continue;
}
}
}
}
return ;
}
signed main(){
read(m),read(n);
if(n==1){cout<<1;return 0;}
if(m==1){cout<<1;return 0;}
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) vis[i][j]=true;
edi=n,edj=m;
DP();
write(Ans*2);
return 0;
}