好神的题啊!

看了这题只会第一个subtask,又参考了HN-CJ鸽王zsy的题解,实在太菜了。

暴力转移是O(nc2),很显然没有分。考虑子任务1,2,只需要转移包含已染色格子的列,然后状态数只有O(nc),对于关键两列(即有染色的列)间,只有5种状态。而这个可以初始化转移,转移讨论有点复杂,而且我不会用数学公式,就不打出吧。转移后即可直接DP。然后对于子任务3,4,把它们分割即可,把两边方案乘起来就行了,于是可以做到O(nc),得到96分的好成绩。然后听Claris所述,DP所有转移操作即为T1的操作,于是可以做到O(n+c)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+,mod=1e9+;
int n,m,tot,ans=,a[N],b[N],c[N],p[N],g[N][];
int qpow(int a,int b)
{
int ret=;
while(b)
{
if(b&)ret=1ll*ret*a%mod;
a=1ll*a*a%mod,b>>=;
}
return ret;
}
struct array{
int mul,add,inv,sum,top,s[N<<],f[N];
array(){mul=inv=;}
void modify(int x,int v)
{
sum=(sum+1ll*(mod-f[x])*mul+mod-add)%mod;
f[x]=1ll*(v-add+mod)*inv%mod,s[++top]=x,sum=(sum+v)%mod;
}
void plus(int v){sum=(sum+1ll*m*v)%mod,add=(add+v)%mod;}
void cover(int v)
{
while(top)f[s[top--]]=;
mul=inv=,add=v,sum=1ll*m*v%mod;
}
void mult(int v)
{
if(v)
sum=1ll*sum*v%mod,mul=1ll*mul*v%mod,add=1ll*add*v%mod,inv=1ll*inv*qpow(v,mod-)%mod;
else cover();
}
int query(int x)
{
if(x)return(1ll*f[x]*mul+add)%mod;
return sum;
}
}F;
void trans(int x,int y,int z,int w)
{
if(x!=y)
{
int fy=F.query(y),sum=(F.query()-fy+mod)%mod;
F.mult((g[z][^w]-g[z][]+mod)%mod);
F.plus((1ll*sum*g[z][]+1ll*fy*g[z][^w])%mod);
F.modify(x,(1ll*sum*g[z][^w]+1ll*fy*g[z][^w])%mod);
F.modify(y,);
}
else{
int sum=F.query();
F.mult((g[z][^w]-g[z][^w]+mod)%mod);
F.plus(1ll*sum*g[z][^w]%mod);
F.modify(x,);
}
}
void build(int x,int y,int z,int w)
{
if(w==x)F.cover(g[z][]),F.modify(x,),F.modify(y,g[z][]);
else if(w==y)F.cover(g[z][]),F.modify(x,g[z][]),F.modify(y,);
else F.cover(g[z][]),F.modify(x,g[z][]),F.modify(y,g[z][]),F.modify(w,);
}
void solve(int x,int y,int z,int w)
{
int ret=;
if(w==x)
{
int fy=F.query(y),sum=(F.query()-fy+mod)%mod;
ret=(1ll*sum*g[z][]+1ll*fy*g[z][])%mod;
}
else if(w==y)
{
int fx=F.query(x),sum=(F.query()-fx+mod)%mod;
ret=(1ll*sum*g[z][]+1ll*fx*g[z][])%mod;
}
else{
int fx=F.query(x),fy=F.query(y),sum=(1ll*F.query()-fx-fy+*mod)%mod;
ret=(1ll*sum*g[z][]+1ll*fx*g[z][]+1ll*fy*g[z][])%mod;
}
ans=1ll*ans*ret%mod;
}
int cal(int x,int y,int z,int u,int v)
{
if(x==u)return y==v?g[z][]:g[z][];
if(x==v)return y==u?g[z][]:g[z][];
if(y==u)return g[z][];
if(y==v)return g[z][];
return g[z][];
}
int main()
{
scanf("%d%d",&n,&m);
int mp[][]={{,,,m-,1ll*(m-)*(m-)%mod},
{,,m-,,1ll*(m-)*(m-)%mod},{,,m-,*m-,2ll*(m-)*(m-)%mod},
{,,*m-,m-,2ll*(m-)*(m-)%mod},{,,m-,m-,1ll*(m-)*(m-)%mod+}};
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]&&a[i]==a[i-]){puts("");return ;}
}
for(int i=;i<=n;i++)
{
scanf("%d",&b[i]);
if(b[i]&&(a[i]==b[i]||b[i]==b[i-])){puts("");return ;}
}
g[][]=;
for(int i=;i<=n;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
g[i][k]=(g[i][k]+1ll*g[i-][j]*mp[j][k])%mod;
int v1=qpow(m-,mod-),v2=qpow(1ll*(m-)*(m-)%mod,mod-);
for(int i=;i<=n;i++)
g[i][]=1ll*g[i][]*v1%mod,g[i][]=1ll*g[i][]*v1%mod,g[i][]=1ll*g[i][]*v2%mod;
for(int i=;i<=n;i++)
if(a[i]||b[i])
{
p[++tot]=i;
if(b[i]&&!a[i])swap(a[i],b[i]),c[i]=;
else if(b[i])c[i]=;
}
int pw=qpow(1ll*(m-)*(m-)%mod+,p[]-);
if(c[p[]]<)F.cover(pw),F.modify(a[p[]],);else ans=pw;
for(int i=;i<=tot;i++)
if(c[p[i-]]==)
if(c[p[i]]==)ans=1ll*ans*cal(a[p[i-]],b[p[i-]],p[i]-p[i-],a[p[i]],b[p[i]])%mod;
else{
if(c[p[i]])swap(a[p[i-]],b[p[i-]]);
build(a[p[i-]],b[p[i-]],p[i]-p[i-],a[p[i]]);
if(c[p[i]])swap(a[p[i-]],b[p[i-]]);
}
else if(c[p[i]]==)
{
if(c[p[i-]])swap(a[p[i]],b[p[i]]);
solve(a[p[i]],b[p[i]],p[i]-p[i-],a[p[i-]]);
if(c[p[i-]])swap(a[p[i]],b[p[i]]);
}
else trans(a[p[i-]],a[p[i]],p[i]-p[i-],c[p[i]]^c[p[i-]]);
if(c[p[tot]]<)ans=1ll*ans*F.query()%mod;
ans=1ll*ans*qpow(1ll*(m-)*(m-)%mod+,n-p[tot])%mod;
printf("%d",ans);
}

[SDOI2019]染色(DP)的更多相关文章

  1. Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)

    #include<bits/stdc++.h>using namespace std;const long long mod=998244353;long long f[200007][2 ...

  2. 【POJ 1112】Team Them Up!(二分图染色+DP)

    Description Your task is to divide a number of persons into two teams, in such a way, that: everyone ...

  3. poj-1112 (二分图染色+dp分组)

    #include <iostream> #include <algorithm> #include <cstring> using namespace std; ; ...

  4. 【xsy1172】 染色 dp

    题目大意:现有$n$条排成一行的木板,每个木板有一个目标颜色.你每次能将一个区间内的木板分别染成它们的目标颜色,而这次染色的代价为这个区间内不同目标颜色的木板的数量的平方.问将全部木板染成目标颜色的最 ...

  5. BZOJ:2958 序列染色 DP

    bzoj2958 序列染色 题目传送门 Description 给出一个长度为N由B.W.X三种字符组成的字符串S,你需要把每一个X染成B或W中的一个. 对于给出的K,问有多少种染色方式使得存在整数a ...

  6. 染色dp(确定一行就可行)

    题:https://codeforces.com/contest/1027/problem/E 题意:给定n*n的方格,可以染黑白,要求相邻俩行”完全“不同或完全相同,对于列也是一样.然后限制不能拥有 ...

  7. 5.29 省选模拟赛 树的染色 dp 最优性优化

    LINK:树的染色 考场上以为这道题要爆蛋了 没想到 推出正解来了. 反正是先写了爆搜的 爆搜最近越写越熟练了 容易想到dp 容易设出状态 f[i][j]表示以i为根的子树内白色的值为j此时黑色的值怎 ...

  8. bzoj2958: 序列染色(DP)

    2958: 序列染色 题目:传送门 题解: 大难题啊(还是我太菜了) %一发大佬QTT 代码: #include<cstdio> #include<cstring> #incl ...

  9. Atcoder Grand Contest 031B(DP,思维)

    #include<bits/stdc++.h>using namespace std;int a[200007];int b[200007];long long dp[200007];lo ...

随机推荐

  1. json解析精度问题

    由于后台传过来的值是float或者double类型,解析之后作为对象放到字典或数组里面,被转成nsstring或者nsnumber会有一定的误差,很正常 解决办法,通过NSNumberFormatte ...

  2. C# 互操作性入门系列(三):平台调用中的数据封送处理

    好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...

  3. torch文档学习笔记

    下面为官方文档学习笔记    http://pytorch.org/docs/0.3.0/index.html 1.torch.Tensor from __future__ import print_ ...

  4. 什么是控制反转IOC

    1.IOC 是什么 IOC- Inversion of Control , 即“控制反转” ,不是一个技术,而是一个设计思想,在java 开发中,IOC意味着将你设计好的Java 对象交个容器控制,而 ...

  5. ES6 之 函数的扩展 尾调用以及尾递归

    函数参数的默认值 function log(x, y) { y = y || 'world' console.log(x + ' ' + y); } log('hello') // hello wor ...

  6. 白痴级教程,新手看过来,具详细实操文档 (word图片复制不过来,0202年了还有这样的不便利,下回研究一下,图片下次补)

    一.环境配置(win10): 1.配置cmd的python环境为arcmap10.2 自带的python解释器(2.7.3)(自带arcpy库) 具体操作: 1我的电脑右击属性,打开 (选中path点 ...

  7. delphi try except与try finally语句用法以及区别

    一.异常的来源 在Delphi的应用程序中,下列的情况都比较有可能产生异常. (1)文件处理 (2)内存分配 (3)Windows资源 (4)运行时创建对象和窗体 (5)硬件和操作系统冲突 二.异常的 ...

  8. Java 知识点(一)

    博主对 Java知识点的整理基于 c语言,整理内容为 Java的重点及与 c语言的差异点或编程通要知识点.水平有限,欢迎指正.(参考书籍<Java 核心技术 卷Ⅰ>) Java 的类名:名 ...

  9. Android studio中2种build.gradle文件介绍

    根目录下的build.gradle通常不需要修改这个文件中的内容,除非需要添加一些全局的项目构建配置 buildscript { repositories { google() //声明代码托管仓库G ...

  10. MySQL的InnoDB的幻读问题

    MySQL InnoDB事务的隔离级别有四级,默认是“可重复读”(REPEATABLE READ). 未提交读(READ UNCOMMITTED).另一个事务修改了数据,但尚未提交,而本事务中的SEL ...