好神的题啊!

看了这题只会第一个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. 十四、CI框架之数据库以参数形式插入操作

    一.代码如下: 二.使用浏览器打开 三.我们查看数据库,被成功插入数据 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  2. 文献阅读报告 - Context-Based Cyclist Path Prediction using RNN

    原文引用 Pool, Ewoud & Kooij, Julian & Gavrila, Dariu. (2019). Context-based cyclist path predic ...

  3. MySQL的异常问题

    异常问题

  4. PSI-BLAST|PHI-BLAST|UniProt|IGV|Galaxy|clustalx

    生物信息学软件: NCBI:BLAST,设定k-mer 默认是全局比对,Blastn是局部比对. PSI-BLAST最灵敏的BLAST,选中部分矩阵后在数据库中查找相应蛋白. PHI-BLAST找氨基 ...

  5. 2016蓝桥杯省赛C/C++A组第三题 方格填数

    题意:如下的10个格子  填入0~9的数字.要求:连续的两个数字不能相邻. (左右.上下.对角都算相邻) 一共有多少种可能的填数方案? 分析:dfs,划定边界,行1~4,列1~3,初始化为INT_IN ...

  6. POJ 1062:昂贵的聘礼

    昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 40715   Accepted: 11839 Descripti ...

  7. CountUp.js 数字跳转效果小插件

    CountUp.js  实现数字跳转效果的小插件 //调用方法 const easingFn = function (t, b, c, d) { var ts = (t /= d) * t; var ...

  8. 分布式CAP定理(转)

    在弄清楚这个问题之前,我们先了解一下什么是分布式的CAP定理. 根据百度百科的定义,CAP定理又称CAP原则,指的是在一个分布式系统中,Consistency(一致性). Availability(可 ...

  9. 干货 | DRDS 与TiDB浅析

    干货 | DRDS 与TiDB浅析 北京it爷们儿 京东云开发者社区  4月17日 在谈论数据库架构和数据库优化的时候,会常听到"分库分表"."分片".&quo ...

  10. Pyspider的简单介绍和初使用

    Pyspider   Pyspider是由国人(binux)编写的强大的网络爬虫系统 Ptspider带有强大的WebUi / 脚本编辑器 / 任务监控器 / 项目管理器以及结果处理器.他支持多种数据 ...