好神的题啊!

看了这题只会第一个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. 下载jQuery

    下载jQuery :https://jquery.com/download/ . 将下载好的文件放到项目中 引入到代码中 <script type="text/javascript&q ...

  2. html 鼠标样式 鼠标悬停 小手样式

    在style中添加cursor:pointer 实现鼠标悬停变成小手样式 先来一个示例 <div style="float:right"> <a class=&q ...

  3. DevOps元数据管理

    元数据是自动化运维的基础,对元数据的管理和查询贯穿整个运维的生命周期.我们从一个元数据的使用场景开始: 双十一抢购火热进行中,某电商后端实例的日志中出现了502错误码,运维平台监测到该异常并发送告警给 ...

  4. php对象:__autoload()函数及单入口文件,__set(), __get(), get_class_methods(),get_class_vars()

    __autoload():当类中找不到相关类的时候,会自动执行__autoload()函数,可以自动加载相关文件 __set() : 当对类的私有变量进行调用赋值时,自动调用该方法.  __get() ...

  5. CPU压力测试--限制到指定范围

    作用:增加CPU使用率到指定范围 1.书写shell脚本增加CPU压力 #! /bin/bash # filename cputest.sh endless_loop() { echo -ne &qu ...

  6. Git 报错:fatal: refusing to merge unrelated histories

    背景:[接上篇git push 出错的随笔]当 pull 远端仓库到本地的时候,出现以下错误: 错误情况: 出错原因:主要原因还是在于本地仓库和远程仓库实际上是独立的两个仓库,假如我之前是直接以 cl ...

  7. count(1),count(*)和count(列)的比较

    转自:https://www.cnblogs.com/Caucasian/p/7041061.html 1.关于count(1),count(*),和count(列名)的区别 相信大家总是在工作中,或 ...

  8. UML-包的设计

    1.准则 1).准则1 包在水平和垂直划分上,要功能性内聚.即:同类关联功能的模块化,将参与共同目的.服务.协作.策略和功能的强相关类型(类或者接口)组织在一起. 如:在NextGen项目中,Pric ...

  9. [Python Cookbook]Pandas: How to increase columns for DataFrame?Join/Concat

    1. Combine Two Series series1=pd.Series([1,2,3],name='s1') series2=pd.Series([4,5,6],name='s2') df = ...

  10. win10设置开机以及开机无密码验证

    1.开机自启动 将程序的exe的快捷方式放入下列文件夹中 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 2.开机无登录验证 ...