nyoj-1273 宣传墙

宣传墙

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 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
来源

河南省第九届省赛

矩阵快速幂解法,加判断数组,时间超短8ms,内存小8648

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int MOD = 997;
const int MAXN = 16;

struct mat
{
    int A[MAXN][MAXN];

    mat()
    {
        memset(A, 0, sizeof(A));
    }

    mat operator * (const mat &a) const
    {
        mat b;
        for (int i = 0; i < MAXN; i++)
        {
            for (int j = 0; j < MAXN; j++)
            {
                for (int k = 0; k < MAXN; k++)
                {
                    b.A[i][j] += A[i][k] * a.A[k][j];
                    b.A[i][j] %= MOD;
                }
            }
        }
        return b;
    }
};

mat map;

bool cmp(int i, int j)  //  状态 j 对状态 i 是否可行 j 是 col 列的状态 i 是 col - 1 列的状态
{
    for (int row = 0; row < 4; row++)
    {
        if ((i >> row) & 1)
        {
            if ((j >> row) & 1)
            {
//                if (row == 3)               //  这个特判有没有都行,因为 i >> 4 肯定为 0
//                {                           //  这样不过是思维更严谨些
//                    return false;
//                }
                if ((i >> (row + 1)) & 1)
                {
                    i -= (1 << (row + 1));  //  等价于 i ^= 1 << (rank + 1),前边的写法不太直观
                }
                else
                {
                    return false;
                }
            }
            else
            {
                continue;
            }
        }
        else
        {
            if ((j >> row) & 1)
            {
                continue;
            }
            else
            {
                return false;
            }
        }
    }
    return true;
}

//  构造单元矩阵
void unit()
{
    for (int i = 0; i < MAXN; i++)
    {
        for (int j = 0; j < MAXN; j++)
        {
            map.A[i][j] = cmp(i, j);
        }
    }
}

int slove(int n)
{
    mat a;
    mat b = map;
    for (int i = 0; i < MAXN; i++)
    {
        a.A[i][i] = 1;
    }
    while (n)
    {
        if (n & 1)
        {
            a = a * b;
        }
        b = b * b;
        n >>= 1;
    }
    return a.A[MAXN - 1][MAXN - 1];
}

int main ()
{
    int T;
    scanf("%d", &T);

    unit();

    while (T--)
    {
        int N, M, K;
        scanf("%d%d%d", &N, &M, &K);
        printf("%d %d\n", slove(M - 1), slove(N - M - K + 1));
    }
    return 0;
}

状态压缩 DP  

滚动数组解法  时间长713ms,内存大 94896

#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\n");  
        }  
        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\n",dp[row][(1<<col)-1]);  
        }  
    }  
    return 0;  
}  


猜你喜欢

转载自blog.csdn.net/qq_36914923/article/details/80109195