//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define ll long long
ll dp[13][1<<12];
int path[500005][3];
int a,b;
int w;
void dfs(int now,int pre,int l)
{
if(l>a) return;
if(l==a)
{
path[w][0]=pre;
path[w++][1]=now;
return;
}
dfs(now<<1,pre<<1|1,l+1);
dfs(now<<1|1,pre<<1,l+1);
dfs(now<<2|3,pre<<2|3,l+2);
}
int main()
{
while(~scanf("%d%d",&a,&b))
{ if(a==0&&b==0) return 0;
if(a*b%2==1)
{
printf("0\n");
continue;
}
w=0;
if(a>b) swap(a,b);
dfs(0,0,0);
memset(dp,0,sizeof(dp));
dp[0][(1<<a)-1]=1;
for(int i=0;i<b;i++)
{
for(int j=0;j<w;j++)
{
dp[i+1][path[j][1]]+=dp[i][path[j][0]];
}
}
printf("%lld\n",dp[b][(1<<a)-1]);
}
return 0;
}
参考博客 :http://blog.csdn.net/u013480600/article/details/19569291
用二进制模拟每一行的情况和他前一行的情况,然后正在用dp 由第一行往下推
二进制表示每一行 方块有三种放的方式 横放 把两格全部标成 1 竖放上边标成 0 下边标成 1这样每一行都能用二进制表示
path 二维 一个存他本身 另一个存他前面那个 所以dp 时 就是dp[i+1][path[j][1]]+=dp[i][path[j][0]]; 下一行的方法+=上一行的方法数
dp[0][(1<<a)-1]=1; 初始化为1 假设第 0行全部是1 这样不会对下一行产生影响
最后直接输出 最后一行全部是1 的dp值就行。。
poj 3420与上题相识 给一个4*n的方块 要你用 1*2的铺满
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define ll long long
int w;
int mod;
struct mat
{
int ma[16][16];
}dat;
void dfs(int now,int pre,int l)
{
if(l>4) return;
if(l==4)
{
dat.ma[pre][now]++;
return;
}
dfs(now<<1,pre<<1|1,l+1);
dfs(now<<1|1,pre<<1,l+1);
dfs(now<<2|3,pre<<2|3,l+2);
}
mat mupl(mat a,mat b)
{
mat c;
memset(c.ma,0,sizeof(c.ma));
for(int i=0;i<16;i++)
{
for(int j=0;j<16;j++)
{
for(int k=0;k<16;k++)
c.ma[i][j]=(c.ma[i][j] + a.ma[i][k]*b.ma[k][j])%mod;
}
}
return c;
}
mat poww(int n)
{
mat e,a=dat;
memset(e.ma,0,sizeof(e.ma));
for(int i=0;i<16;++i)
e.ma[i][i]=1;
while(n)
{
if(n&1) e=mupl(a,e);
n>>=1;
a=mupl(a,a);
}
return e;
}
int main()
{
int n;
memset(dat.ma,0,sizeof(dat.ma));
dfs(0,0,0);
while(~scanf("%d%d",&n,&mod))
{
if(!n&&!mod) return 0;
if(mod==1)
{
printf("0\n");
continue;
}
if(n==1||n==0)
{
printf("1\n");
continue;
}
mat ans=poww(n);
printf("%d\n",ans.ma[15][15]);
}
return 0;
}
参考 http://blog.csdn.net/u013480600/article/details/19644847
由于该题是列固定为4,所以pre和now的值最多有16种,设A[pre][now]=1表示兼容对前行pre和后行now的二进制形式兼容有1种情况(该值不是1就是0)。则令B=A*A,则
B[2][3]=A[2][0]*A[0][3]
+A[2][1]*A[1][3]
+A[2][2]*A[2][3]
+A[2][3]*A[3][3]
即(A*A)[2][3]表示pre=2与now=3之间还间隔了一行,并且pre与now远程兼容有多少种方式。(pre与now的远程距离为1).由于目标矩阵有n行,行号从1到n,则我们假想目标矩阵的上面还有1行是第0行,并且二进制形式为全1序列。所以我们要求的是第0行和第n行距离为n-1的远程兼容有多少种方法。
即求得就是(A^n)[0][15]的值,该值还要对mod求余。