题解 P2435 【染色】
RainFestival · · 题解
Update on 2026/05/12: 修改了代码中的错误(感谢 @DaydreamWarrior 与 @REFLAME_ASH 指出),优化了代码,采用了规范的格式。
题意:给你一个
首先对于
对于
我们从上到下,从左到右考虑问题。假设当前填到格子
于是,我们考虑下一个格子
-
需要与上方
(i^*-1,j^*) 格子颜色不同。 -
如果
j^*\neq 1 ,那么需要与左方(i^*,j^*-1) 格子颜色不同。
这两个格子的颜色信息都记录在
我们只填到第
实现的时候,考虑用
时间复杂度
下面是笔者的
::::info[代码]
#include<cstdio>
const int mod=376544743;
int dp[2][300005],b[15],ans,sp1[100005],sp2[100005];
int n,m,kk,now,maxs,s1,s2;
void update(int x1,int x2){dp[now][x2]=(dp[now][x2]+dp[1-now][x1])%mod;}
void put(int x,int y,int lst){if (y/b[m-1]!=x&&(y%kk!=x||lst)) update(y,(y*kk+x)%b[m]);}
int check(int x,int y,int m)
{
for (int i=1;i<=m;i++)
{
if (x%kk==y%kk) return 0;
x=x/kk,y=y/kk;
}
return 1;
}
int main()
{
scanf("%d%d%d",&n,&m,&kk);
if (kk==2)
{
int flag=1;
for (int i=1;i<=m;i++) scanf("%d",&sp1[i]);
for (int i=1;i<=m;i++) scanf("%d",&sp2[i]);
for (int i=1;i<=m;++i)
{
if ((i>1)&&(sp1[i]==sp1[i-1]||sp2[i]==sp2[i-1])) flag=0;
if ((sp1[i]+n)%2==sp2[i]) flag=0;
}
printf("%d\n",flag);
return 0;
}
b[0]=1;for (int i=1;i<=m;i++) b[i]=b[i-1]*kk;
maxs=b[m]-1;
for (int i=1;i<=m;i++)
{
int x,y=-1;
scanf("%d",&x);
if (i!=1&&x==y) return puts("0"),0;
s1=s1*kk+x;y=x;
}
for (int i=1;i<=m;i++)
{
int x,y=-1;
scanf("%d",&x);
if (i!=1&&x==y) return puts("0"),0;
s2=s2*kk+x;y=x;
}
dp[0][s1]=1;
now=0;
for (int i=1;i<n;i++)
for (int j=1;j<=m;j++)
{
if (i==1&&j!=m) continue;
if (i==n-1&&j==m) break;
int lst=(j==m);
now=1-now;
for (int k=0;k<=maxs;k++) dp[now][k]=0;
for (int k=0;k<=maxs;k++)
if (dp[1-now][k]) for (int p=0;p<kk;p++) put(p,k,lst);
}
for (int i=0;i<=maxs;i++) if (dp[now][i]&&check(i,s2,m)) ans=(ans+dp[now][i])%mod;
printf("%d\n",ans);
return 0;
}
::::
消耗时间
::::info[一些怀旧故事]
这篇题解本来是由笔者于七年前的一个五月,
在七年后的这个五月,inline,register之类的,现在已经被弃用的东西;还有把所有的 i++ 都改成了 ++i,但是实际上这些编译器最终都会编译成同样的机器码;还有努力不用拼音,但是最后发现实际上缺乏意义的变量名,等等。笔者现在猜想可能是因为当时笔者一直超时(