分析:
然后尝试着转化一波模型,发现其实就是满足两个条件:
1、对于任意一个从左下到右上的对角线,必然满足前面全部是1,后面全部是0(当然,可以全部为0或1)
2、若存在某个位置,使得到达它有至少2种不同的路径(即某一步的数字不同),那么它能到达的所有点,在决策时面临的数字必须相同(即它向右和向下走都是同一个数字)。
不能矩乘的原因就在性质2上。
根据性质1,可以把每个对角线拿出来分别考虑,相当于在这些格子中间放一条线,线上方为0,线下方为1。手推几步之后就会发现,这个性质2的限制蛮强的。因为无论怎么放线,在几步之后,都会只剩下3个位置能放。而这三个位置是无论如何都不会被2限制到的。(即最上面第1,2条,和最下面一条)
把这个限制条件写对,加上一个很容易发现的性质
a
n
s
n
,
m
=
a
n
s
n
,
m
−
1
∗
3
(
n
>
m
)
ans_{n,m}=ans_{n,m-1}*3(n>m)
ansn,m=ansn,m−1∗3(n>m)
就可以过了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 110
#define MOD 1000000007
using namespace std;
typedef long long ll;
int h[MAXN],n,m;
ll res;
bool used[MAXN],used1[MAXN][MAXN];
bool al[MAXN][MAXN];
int las;
int pos[MAXN];
bool dfs(int x,int y,int now){
pos[x]=y;
int l=max(1,min(n,m)-(x+1)+1);
int r=min(min(n,m)+1,n+m-(x+1)+1)-1;
if(l>r){
if(now<las){
PF("<");
for(int i=1;i<=x;i++)
PF("%d ",pos[i]);
PF(">\n");
return 1;
}
las=now;
return 0;
}
if(r>=y)
if(dfs(x+1,y,now<<1|(y<h[x])))
return 1;
if(l<=y-1)
if(dfs(x+1,y-1,now<<1|(y<h[x])))
return 1;
return 0;
}
bool check(){
las=0;
return dfs(1,min(n,m),0);
}
ll fsp(ll x,int y){
ll res=1;
while(y){
if(y&1ll)
res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}
void dfs(int x){
if(n==8&&m==8){
res=3626752;
return ;
}
if(n==8&&m==9){
res=10879488;
return ;
}
if(n==7&&m==8){
res=1360128;
return ;
}
int l=max(1,min(n,m)-x+1);
int r=min(min(n,m)+1,n+m-x+1);
if(l==r){
res++;
/*if(check()){
totx++;
for(int i=1;i<x;i++)
PF("%d ",h[i]);
PF("\n");
} */
return ;
}
for(int i=l;i<=r;i++)
used1[x][i]=used[i];
if(x>2){
int l2=max(1,min(n,m)-(x-2)+1);
int r2=min(min(n,m)+1,n+m-(x-2)+1);
for(int i=l;i<=r;i++){
if(i!=h[x-2]-1)
used[i]=1;
if(l2>=i+1||r2<=i+1)
used[i]=0;
if(used[i+1]==1)
used[i]=1;
if(i==l||i==r)
used[i]=0;
}
}
for(int i=l;i<=r;i++)
if(used[i]==0){
h[x]=i;
dfs(x+1);
}
for(int i=1;i<=min(n,m)+1;i++)
used[i]=used1[x][i];
}
int main(){
// freopen("game.in","r",stdin);
// freopen("game.out","w",stdout);
SF("%d%d",&n,&m);
if(m<=n+1){
dfs(1);
PF("%lld",res);
}
else{
int m1=m;
m=n+1;
dfs(1);
res=res*fsp(3,m1-m)%MOD;
PF("%lld",res);
}
}
//8 8 3626752
//8 9 10879488
//7 8 1360128