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
【提示】样例说明:
数据范围与提示: 对于 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 */
原文:https://www.cnblogs.com/gaojunonly1/p/10366612.html