首先我们可以设置DP状态为 f i , x , y f_{i,x,y} fi,x,y表示当前DP到第 i i i列,两个格子的颜色分别为 x , y x,y x,y的方案数。显然我们需要优化。
考虑想办法快速跳过中间两个位置都空的格子。
考虑枚举起始列和终止列的状态,然后考虑中间的空格子的方案数,注意我们这里是在假设两边都已经确定了的情况下进行计数。
本质不同的情况有5种(其中不同字母表示的颜色不同):
处理出 g [ l ] [ 0 / 1 / 2 / 3 / 4 ] g[l][0/1/2/3/4] g[l][0/1/2/3/4]表示中间空列数量为 l − 1 l-1 l−1的时候两种状态之间的转移系数。
处理 g g g也是考虑DP,注意这里只算考虑中间空列的填空数量,所以对于 3 , 4 , 5 3,4,5 3,4,5三种情况我们需要修正,同时 3 , 4 3,4 3,4是包含了两种状态的,需要在转移中体现出来,具体可以看代码。
有的列是两个格子填满了的,显然以这些列为分界线两边的格子互不干扰,于是我们把这些区间各自的答案算出来就行了。
发现转移可以用D1T1的东西优化,然后就没了。
代码(由于我看的是zsy神仙的题解,代码基本上就是按照zsy的思路写的):
#include
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){
return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int mod=1e9+9;
inline int add(int a,int b){
a+=b-mod;return a+(a>>31&mod);}
inline int dec(int a,int b){
a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){
ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b){
int r=1;for(;b;b>>=1,a=mul(a,a))
(b&1)&&(r=mul(r,a));return r;
}
inline void Inc(int &a,int b){
a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){
a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){
a=mul(a,b);}
inline void ex_gcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;return ;}ex_gcd(b,a%b,y,x);y-=a/b*x;
}
inline int inv(int a){
int x,y;ex_gcd(mod,a,y,x);
return x+(x>>31&mod);
}
cs int N=1e5+7;
int n,m,k,ans=1;
int a[N],b[N],c[N],p[N],g[N][5];
inline void init_g(){
int coef[5][5]={
{
0,1,0,m-2,mul(m-2,m-3)},
{
1,0,m-2,0,mul(m-2,m-3)},
{
0,2,m-2,2*m-5,mul(2,mul(m-3,m-3))},
{
2,0,2*m-5,m-2,mul(2,mul(m-3,m-3))},
{
1,1,m-3,m-3,mul(m-3,m-4)+1}
};g[0][0]=1;
for(int re i=1;i<=n;++i)
for(int re j=0;j<5;++j)if(g[i-1][j])
for(int re k=0;k<5;++k)Inc(g[i][k],mul(g[i-1][j],coef[j][k]));
int v1=inv(m-2),v2=inv(mul(m-2,m-3));
for(int re i=1;i<=n;++i){
Mul(g[i][2],v1);
Mul(g[i][3],v1);
Mul(g[i][4],v2);
}
}
inline int cal(int x,int y,int l,int u,int v){
if(x==u)return y==v?g[l][0]:g[l][2];
if(x==v)return y==u?g[l][1]:g[l][3];
if(y==u)return g[l][3];
if(y==v)return g[l][2];
return g[l][4];
}
struct array{
int f[N],tag_mul,inv_mul,tag_add,sum,st[N<<2|7],tp;
array(){
tag_mul=inv_mul=1;}
inline int get(int x){
return add(mul(f[x],tag_mul),tag_add);}
inline int query(){
return sum;}
inline void set(int x,int y){
Dec(sum,get(x));Inc(sum,y);st[++tp]=x;
f[x]=mul(inv_mul,dec(y,tag_add));
}
inline void cov(int a){
while(tp)f[st[tp--]]=0;
sum=mul(a,m);tag_mul=inv_mul=1,tag_add=a;
}
inline void plus(int a){
Inc(sum,mul(a,m));
Inc(tag_add,a);
}
inline void mult(int a){
if(!a)return cov(0);
Mul(sum,a);Mul(tag_mul,a);
Mul(tag_add,a),Mul(inv_mul,inv(a));
}
}F;
inline void start(int x,int y,int l,int w){
if(w==x)
F.cov(g[l][2]),F.set(x,0),F.set(y,g[l][0]);
else if(w==y)
F.cov(g[l][3]),F.set(x,g[l][1]),F.set(y,0);
else
F.cov(g[l][4]),F.set(x,g[l][3]),F.set(y,g[l][2]),F.set(w,0);
}
inline void trans(int x,int y,int l,int w){
if(x==y){
int fs=F.query();
F.mult(dec(g[l][0^w],g[l][2^w]));
F.plus(mul(fs,g[l][2^w]));
F.set(x,0);
}else {
int fy=F.get(y),fs=dec(F.query(),fy);
F.mult(dec(g[l][2^w],g[l][4]));
F.plus(add(mul(g[l][4],fs),mul(g[l][3^w],fy)));
F.set(x,add(mul(g[l][3^w],fs),mul(g[l][1^w],fy)));
F.set(y,0);
}
}
inline void finish(int x,int y,int l,int w){
int res=0;
if(w==x){
int fy=F.get(y),fs=dec(F.query(),fy);
res=add(mul(fy,g[l][0]),mul(fs,g[l][2]));
}else if(w==y){
int fx=F.get(x),fs=dec(F.query(),fx);
res=add(mul(fx,g[l][1]),mul(fs,g[l][3]));
}else {
int fx=F.get(x),fy=F.get(y),fs=dec(F.query(),add(fx,fy));
res=add(mul(fs,g[l][4]),add(mul(fx,g[l][3]),mul(fy,g[l][2])));
}
Mul(ans,res);
}
signed main(){
#ifdef zxyoi
freopen("dye.in","r",stdin);
#endif
n=gi(),m=gi();init_g();
for(int re i=1;i<=n;++i)a[i]=gi();
for(int re i=1;i<=n;++i)b[i]=gi();
for(int re i=1;i<=n;++i)if(a[i]||b[i]){
p[++k]=i;a[k]=a[i],b[k]=b[i];
if(b[k]){
if(!a[k])std::swap(a[k],b[k]),c[k]=1;
else {
if(a[k]==b[k])return puts("0"),0;
c[k]=2;
}
}
}
int pw=power(mul(m-1,m-2)+1,p[1]-1);
if(c[1]<2)F.cov(pw),F.set(a[1],0);
else ans=pw;
for(int re i=2;i<=k;++i){
if(c[i-1]==2){
if(c[i]==2)Mul(ans,cal(a[i-1],b[i-1],p[i]-p[i-1],a[i],b[i]));
else {
if(c[i])std::swap(a[i-1],b[i-1]);
start(a[i-1],b[i-1],p[i]-p[i-1],a[i]);
if(c[i])std::swap(a[i-1],b[i-1]);
}
}else {
if(c[i]==2){
if(c[i-1])std::swap(a[i],b[i]);
finish(a[i],b[i],p[i]-p[i-1],a[i-1]);
if(c[i-1])std::swap(a[i],b[i]);
}else trans(a[i-1],a[i],p[i]-p[i-1],c[i]^c[i-1]);
}
}
if(c[k]<2)Mul(ans,F.query());
Mul(ans,power(mul(m-1,m-2)+1,n-p[k]));
cout<<ans<<"\n";
return 0;
}