题目描述:
ALPHA 小镇风景美丽,道路整齐,干净,到此旅游的游客特别多。CBA 镇长准备在一条道路南 面 4*N 的墙上做一系列的宣传。为了统一规划,CBA 镇长要求每个宣传栏只能占相邻的两个方格 位置。但这条道路被另一条道路分割成左右两段。CBA 镇长想知道,若每个位置都贴上宣传栏, 左右两段各有有多少种不同的张贴方案。 例如: N=6,M=3, K=2, 左,右边各有 5 种不同的张贴方案
输入描述:
第一行: T 表示以下有 T 组测试数据 ( 1≤T ≤8 )
接下来有T行, 每行三个正整数 N M K 分别表示道路的长度,另一条道路的起点和宽度
(1≤ N ,M ≤ 1 000 000, 1≤ K ≤ 100000)
输出描述:
每组测试数据,输出占一行:两个整数,分别表示左右两段不同的张贴方案数。由于方案总数
可能很大,请输出对 997 取模后的结果。
样例输入:
复制
2
6 3 2
5 3 2
样例输出:
5 5
5 1
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f3f
const int mod=997;
using namespace std;
int N,M=4;
int dp[2][1<<4];
void dfs(int i,int j,int state,int next)
{//i表示当前摆放第i列,j表示当前摆放第i行
//state表示第i列当前状态,next表示对下一列的影响
if(j==M)//
{
dp[(i+1)%2][next]+=dp[i][state];
//所有可以到达next状态的摆放数之和
dp[(i+1)%2][next]%=mod;
return;
}
if(state&(1<<j))
dfs(i,j+1,state,next);
if(!((1<<j)&state))//某个位置为空,防1*2的
dfs(i,j+1,state,next|(1<<j));
if(j+1<M&&!((1<<j)&state)&&!((1<<(j+1))&state))
dfs(i,j+2,state,next);
//同一列某一位置为空且下一行也为空,防2*1的
}
int work(int n)
{
memset(dp,0,sizeof(dp));
dp[1][0]=1;
for(int i=1;i<=n;i++)//遍历列
{
for(int j=0;j<(1<<M);j++)//遍历所有状态
{
if(dp[i%2][j])
dfs(i%2,0,j,0);
}
for(int j=0;j<(1<<M);j++)
{
dp[i%2][j]=0;
}
}
return dp[(n+1)%2][0];
}
int main()
{
int t;
// printf("%d %d",0&1,1|1);
scanf("%d",&t);
while(t--)
{
int l,r;
scanf("%d%d%d",&N,&l,&r);
printf("%d %d\n",work(l-1),work(N-l-r+1));
}
return 0;
}