一本通1594涂抹果酱


1594:涂抹果酱

时间限制: 1000 ms         内存限制: 524288 KB

【题目描述】

Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕。蛋糕俯视图是一个 N×M 的矩形,它被划分成 N×M 个边长为 1×1 的小正方形区域(可以把蛋糕当成 N 行 M 列的矩阵)。蛋糕很快做好了,但光秃秃的蛋糕肯定不好看!所以,Sam 要在蛋糕的上表面涂抹果酱。果酱有三种,分别是红果酱、绿果酱、蓝果酱,三种果酱的编号分别为 1,2,3。为了保证蛋糕的视觉效果,Admin 下达了死命令:相邻的区域严禁使用同种果酱。但 Sam 在接到这条命令之前,已经涂好了蛋糕第 K 行的果酱,且无法修改。

现在 Sam 想知道:能令 Admin 满意的涂果酱方案有多少种。请输出方案数 mod 106 。若不存在满足条件的方案,请输出 0。

【输入】

输入共三行。

第一行:N,M;

第二行:K;

第三行:M 个整数,表示第 K 行的方案。

字母的详细含义见题目描述,其他参见样例。

【输出】

输出仅一行,为可行的方案总数。

【输入样例】

2 2 
1 
2 3

【输出样例】

3

【提示】

样例说明:

方案一 方案二 方案三
2 3
2 3 2 3
1 2
3 1 3 2

数据范围与提示:

对于 30% 的数据,1≤N×M≤20;

对于 60% 的数据,1≤N≤1000,1≤M≤3;

对于 100% 的数据,1≤N≤10000,1≤M≤5。

sol:三进制的状压,稍微麻烦一点点,把满足条件的状态预处理出来,m=5时35中大约有55个是满足的,所以复杂度就会小很多,转移复杂度n*55*55 

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-');
        ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48);
        ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x<10)
    {
        putchar(x+'0');
        return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
inline void writeln(ll x)
{
    write(x);
    putchar('\n');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) writeln(x)
const int Mod=1000000;
int n,m,K,Start,Bin[10];
int Id[505],Zt_cnt=0;
struct Zhuangt_Used
{
    int Zt,Num[6];
}Zhuangt[60];
bool Can[60][60];
int dp[10005][60];
inline void Solve(int nn)
{
    int i,j,k;
    dp[1][Id[Start]]=1;
    for(i=2;i<=nn;i++)
    {
        for(j=1;j<=Zt_cnt;j++) if(dp[i-1][j])
        {
            for(k=1;k<=Zt_cnt;k++) if(Can[j][k])
            {
                dp[i][k]+=dp[i-1][j];
                dp[i][k]-=(dp[i][k]>=Mod)?Mod:0;
            }
        }
    }
    return;
}
inline int Get(int nn)
{
    int i,ans=0;
    for(i=1;i<=Zt_cnt;i++)
    {
        ans+=dp[nn][i];
        ans-=(ans>=Mod)?Mod:0;
    }
    return ans;
}
int main()
{
    int i,j,k;
    R(n); R(m); R(K);
    Bin[0]=1;
    for(i=1;i<=m;i++) Bin[i]=Bin[i-1]*3;
    for(i=0;i<Bin[m];i++)
    {
        int Num[6]={0},y=i;
        *Num=0;
        while(y)
        {
            Num[++*Num]=y%3;
            y/=3;
        }
        bool Bo=1;
        for(j=2;j<=m&&Bo;j++) if(Num[j]==Num[j-1]) Bo=0;
        if(!Bo) continue;
        Id[i]=++Zt_cnt;
        Zhuangt[Zt_cnt].Zt=i;
        for(j=1;j<=m;j++) Zhuangt[Zt_cnt].Num[j]=Num[j];
    }
    for(i=1;i<Zt_cnt;i++)
    {
        Can[i][i]=0;
        for(j=i+1;j<=Zt_cnt;j++)
        {
            bool Bo=1;
            for(k=1;k<=m&&Bo;k++) if(Zhuangt[i].Num[k]==Zhuangt[j].Num[k]) Bo=0;
            Can[i][j]=Can[j][i]=Bo;
        }
    }
    for(i=1;i<=m;i++)
    {
        int x=read()-1; Start+=Bin[i-1]*x;
    }
    Solve(max(K,n-K+1));
    Wl(1LL*Get(K)*Get(n-K+1)%Mod);
    return 0;
}
/*
input
2 2
1
2 3
output
3

input
100 1
50
3
output
602688
*/
View Code

猜你喜欢

转载自www.cnblogs.com/gaojunonly1/p/10366612.html
今日推荐