1273-宣传墙
内存限制:64MB 时间限制:1000ms 特判: No
通过数:14 提交数:50 难度:4
题目描述:
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
AC:代码 0ms
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef long long int lli;
typedef unsigned long long llu;
const int maxn = 1<<4;
const int mod = 997;
struct matrix{
int s[maxn][maxn];
}x;
int n,m,k;
int s1,s2;
matrix MulMatrix(matrix a,matrix b,int c,int d,int e)
{
matrix res;
for(int i = 0;i<c;i++){
for(int j = 0;j<d;j++){
int x = 0;
for(int k = 0;k<e;k++){
x = (x + a.s[i][k] * b.s[k][j])%mod;
}
res.s[i][j] = x;
}
}
return res;
}
matrix MatrixPow(matrix a,int b)
{
matrix res;
memset(res.s,0,sizeof(res.s));
for(int i = 0;i<maxn;i++){
res.s[i][i] = 1;
}
while(b)
{
if(b&1) res = MulMatrix(res,a,1,maxn,maxn);
b >>= 1;
a = MulMatrix(a,a,maxn,maxn,maxn);
}
return res;
}
void dfs(int i,int j,int k,int u)//i 行 j 这一列的状态 k 下一列 u (ii)
{
if(u == 4){
x.s[i][k] ++;
return;
}
if((j&(1<<u))){
dfs(i,j,k,u+1);
return;
}
dfs(i,j|(1<<u),k|(1<<u),u+1);
if(u+1<4 && !(j&(1<<u)) && !(j&(1<<(u+1)))){
dfs(i,j|(1<<u)|(1<<(u+1)),k,u+2);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&m,&k);
int s1 = m-1;
if(s1 == 0){
printf("0 ");
} else {
memset(x.s,0,sizeof(x.s));
for(int i = 0;i<maxn;i++){
dfs(i,i,0,0);
}
matrix y = MatrixPow(x,s1);
printf("%d ",y.s[0][0]%mod);
}
s2 = n - s1 - k;
if(s2 == 0){
printf("0
");
} else {
memset(x.s,0,sizeof(x.s));
for(int i = 0;i<maxn;i++){
dfs(i,i,0,0);
}
matrix y = MatrixPow(x,s2);
printf("%d
",y.s[0][0]%mod);
}
}
return 0;
}
在网上找到了一种简单一点的代码贴一下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const int col = 4;
int row;
int dp[900000][1<<4];
void dfs(int r,int c,int pre,int now)
{
if(c==col)
{
dp[r][now] += dp[r-1][pre];
dp[r][now] %= 997;
return ;
}
if(c+1<=col)
{
dfs(r,c+1,pre<<1,(now<<1)|1);
dfs(r,c+1,(pre<<1)|1 ,now<<1);
}
if(c+2<=col)
{
dfs(r,c+2,(pre<<2)|3,(now<<2)|3);
}
}
int main()
{
int T,N,M,K;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&N,&M,&K);
row = M - 1;
if(row<=0)
{
printf("0 ");
}
else
{
memset(dp,0,sizeof(dp));
dp[0][(1<<col)-1] = 1;
for(int i=1;i<=row;i++)
{
dfs(i,0,0,0);
}
printf("%d ",dp[row][(1<<col)-1]);
}
row = N - M - K + 1;
if(row<=0)
{
printf("0
");
}
else
{
memset(dp,0,sizeof(dp));
dp[0][(1<<col)-1] = 1;
for(int i=1;i<=row;i++)
{
dfs(i,0,0,0);
}
printf("%d
",dp[row][(1<<col)-1]);
}
}
return 0;
}