题目链接:http://nyoj.top/web/contest/problem/cid/13/num/B
题目:
用1*2的地砖,填满4*N的墙,有多少种方案。
题解:
状压dp,枚举每个状态的可能转移状态,再计算。
#include<bits/stdc++.h>
using namespace std;
const int mod=997;
const int maxn=1e6+10;
int a[maxn][16];
int main()
{
a[1][0]=1; //转移到第一列的时候,可能的方案为1。因为无法填入,所以只有0这一种状态
for(int i=2;i<1e6+5;i++) //合法状态0 3 6 9 12 15
{
a[i][0]=(a[i-1][0]+a[i-1][3]+a[i-1][9]+a[i-1][12]+a[i-1][15])%mod;
a[i][3]=(a[i-1][0]+a[i-1][12])%mod;
a[i][6]=(a[i-1][9])%mod;
a[i][9]=(a[i-1][0]+a[i-1][6])%mod;
a[i][12]=(a[i-1][0]+a[i-1][3])%mod;
a[i][15]=(a[i-1][0])%mod;
}
int t;
cin>>t;
while(t--)
{
int n,m,k;
cin>>n>>m>>k;
int l=m-1,r=n-(k+m-1);
printf("%d %d\n", a[l+1][0], a[r+1][0]); //输出下一列没溢出来的状态
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
long long dp[2][20];
const int mod=997;
int n=1000000,m=4;
int a[1000005];
void f()
{
int total=1<<m,pre=0,now=1;
memset(dp[now],0,sizeof(dp[now]));
dp[now][0]=1;
for(int i=0;i<n;i++) //列
{
for(int j=0;j<m;j++) //行
{
swap(now,pre);
memset(dp[now],0,sizeof(dp[now]));
for(int S=0;S<total;S++) //枚举状态
{
if( dp[pre][S] )
{
dp[now][S^(1<<j)]=(dp[now][S^(1<<j)]+dp[pre][S])%mod;
if( j && S&(1<<(j-1)) && !(S&(1<<j)))
dp[now][S^(1<<(j-1))]=(dp[now][S^(1<<(j-1))]+dp[pre][S])%mod;
}
}
}
a[i]=dp[now][0];
}
}
int main()
{
int t;
cin>>t;
f();
while(t--)
{
int d,b,c;
cin>>d>>b>>c;
int x1=b-1;
int x2=d-(b+c-1);
cout<<a[x1-1]<<' ';
cout<<a[x2-1]<<endl;
}
}