Codeforces 979E Kuro and Topological Parity(dp)
题意:有 \(n\) 个点,每个点要么被涂黑,要么被涂白,要么没有颜色。
现在你要:
- 给没有颜色的点图上颜色(黑色或白色)
- 在这 \(n\) 个点中连若干条有向边,可以不连通。但是只能从编号小的点连向编号大的点,且不能有重边和自环。
定义一条路径 \(p_1 \to p_2 \to \dots p_k\) 是好的,当且仅当对于 \(i \in [1,k-1]\),\(c_{p_i} \neq c_p_{i+1}\)。
特别地,一个点组成的路径也是好的。
求有多少种涂色+构图的方法使得原图中好的路径的个数模 \(2\) 余 \(k\),答案对 \(10^9+7\) 取模。
\(1 \leq n \leq 50\),其实可以加强到 \(1 \leq n \leq 10^5\)
先抛开构图不谈,考虑对于已知的图 \(G\),怎样求它的好的路径的条数。
由于我们只能从编号小的点向编号大的点连边,那么原序列的一种拓扑序一定是 \(1,2,3,\dots n\)。
用拓扑排序的方法,设 \(g_x=\) 以 \(x\) 结尾的好的路径的条数。
那么 \(g_x=\sum\limits_{(y,x)\in E \& c_y\neq c_x}g_y+1\),非常好理解,枚举上一个点转移,或者单独成一条路径。
总条数 \(=\sum g_i\)。
回到本题上来,本题的 \(g_x\) 都是在 \(\mod 2\) 意义上的。
分析上面那个 \(g_x\) 的式子,不难发现,假设我们要连指向 \(x\) 的边,那么对于 \(y<x\) 且 \(c_y=c_x\) 的点,边 \((y,x)\) 存不存在是无关紧要的,因为它不会影响 \(g_x\) 的奇偶性。
同理,\(g_y \mod 2=0\) 的 \(y\) 也不会对 \(g_x\) 的奇偶性产生影响。
那么现在问题就在于 \(g_y \mod 2=1\) 且 \(c_x \neq c_y\) 的点存不存在。
假设存在至少 \(1\) 个这样的点,考虑随便连剩下 \(i-2\) 条边,共 \(2^{i-2}\) 条边,那么会有怎样的情况呢?
- 如果这 \(i-2\) 条边对 \(g_x\) 的贡献为奇数,那么连边 \((y,x)\) 会导致 \(g(x)\mod 2=0\),反之 \(g(x)\mod 2=1\)
- 如果这 \(i-2\) 条边对 \(g_x\) 的贡献为偶数,那么连边 \((y,x)\) 会导致 \(g(x)\mod 2=1\),反之 \(g(x)\mod 2=0\)
由此可见,无论剩下 \(i-2\) 条边连或不连,你都可以控制 \((y,x)\) 的连或不连来达到你想要的奇偶性。
这个性质对我们的解法有极大的启发性。
设 \(f_{i,j,b,w}\) 表示:
- 考虑到第 \(i\) 个点
- 目前好的路径的总条数 \(\mod 2\) 余 \(j\)
- 是否存在 \(g_x \mod 2=1\) 的黑点的状态为 \(b\)
- 是否存在 \(g_x \mod 2=1\) 的白点的状态为 \(w\)
采用正推进行转移。枚举 \(i+1\) 号点填的颜色,这里以黑色为例。
- 如果 \(w=1\),由以上性质,\(g_{i+1}\) 为奇数和偶数的情况各占一半,各 \(2^{i-1}\),再根据乘法原理乘个 \(dp_{i,j,b,w}\) 即可。
- 如果 \(w=0\),由以上性质,\(g_1,g_2,\dots,g_i\) 要么对 \(g_{i+1}\) 没有贡献,要么对 \(g_{i+1}\) 的贡献为偶数。再加上原本就有的 \(1\),故对于所有 \(2^i\) 种连法,都有 \(g_{i+1}\) 为奇数。乘法原理转移即可。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef pair<int,int> pii;
const int MOD=1e9+7;
inline void inc(int &x,int y){x+=y;if(x>=MOD) x-=MOD;}
int n,p,a[55],dp[55][2][2][2],pw2[55];
//dp[i][j][b][w]
//we have connected edges among the first i points
//the parity of the number of good paths at present is j
//whether there exists "odd black" is b
//whether there exists "odd white" is w
int main(){
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
pw2[0]=1;
for(int i=1;i<=n;i++) pw2[i]=pw2[i-1]*2%MOD;
if(a[1]!=1) dp[1][1][1][0]=1;
if(a[1]!=0) dp[1][1][0][1]=1;
for(int i=1;i<n;i++) for(int j=0;j<2;j++)
for(int b=0;b<2;b++) for(int w=0;w<2;w++){
if(a[i+1]!=1){//black
if(w){
inc(dp[i+1][j^1][1][1],1ll*dp[i][j][b][w]*pw2[i-1]%MOD);//g[i+1] is odd
inc(dp[i+1][j][b][1],1ll*dp[i][j][b][w]*pw2[i-1]%MOD);//g[i+1] is even
}
else inc(dp[i+1][j^1][1][0],1ll*dp[i][j][b][w]*pw2[i]%MOD);
}
if(a[i+1]!=0){//white
if(b){
inc(dp[i+1][j^1][1][1],1ll*dp[i][j][b][w]*pw2[i-1]%MOD);
inc(dp[i+1][j][1][w],1ll*dp[i][j][b][w]*pw2[i-1]%MOD);
}
else inc(dp[i+1][j^1][0][1],1ll*dp[i][j][b][w]*pw2[i]%MOD);
}
}
// for(int i=1;i<=n;i++) for(int j=0;j<2;j++)
// for(int b=0;b<2;b++) for(int w=0;w<2;w++)
// printf("%d %d %d %d %d\n",i,j,b,w,dp[i][j][b][w]);
int ans=0;
for(int b=0;b<2;b++) for(int w=0;w<2;w++)
inc(ans,dp[n][p][b][w]);
printf("%d\n",ans);
return 0;
}
Codeforces 979E Kuro and Topological Parity(dp)的更多相关文章
- Codeforces 979E Kuro and Topological Parity - 动态规划 - 组合数学
题目传送门 传送点 题目大意 给定$n$个标号依次为$1, 2, \cdots, n$的点,其中一些点被染成一些颜色,剩下的点没有染色.你需要添加一些有向边并将剩下的点染色,满足有向边从编号小的一端指 ...
- codeforces 425C Sereja and Two Sequences(DP)
题意读了好久才读懂....不知道怎么翻译好~~请自便~~~ http://codeforces.com/problemset/problem/425/C 看懂之后纠结好久...不会做...仍然是看题解 ...
- Codeforces 629C Famil Door and Brackets(DP)
题目大概说给一个长m的括号序列s,要在其前面和后面添加括号使其变为合法的长度n的括号序列,p+s+q,问有几种方式.(合法的括号序列当且仅当左括号总数等于右括号总数且任何一个前缀左括号数大于等于右括号 ...
- Codeforces Beta Round #13 C. Sequence (DP)
题目大意 给一个数列,长度不超过 5000,每次可以将其中的一个数加 1 或者减 1,问,最少需要多少次操作,才能使得这个数列单调不降 数列中每个数为 -109-109 中的一个数 做法分析 先这样考 ...
- codeforces #267 C George and Job(DP)
职务地址:http://codeforces.com/contest/467/problem/C 太弱了..这题当时都没做出来..思路是有的,可是自己出的几组数组总是过不去..今天又又一次写了一遍.才 ...
- Codeforces 403D: Beautiful Pairs of Numbers(DP)
题意:转换模型之后,就是1~n个数中选k个,放到一个容量为n的背包中,这个背包还特别神奇,相同的物品摆放的位置不同时,算不同的放法(想象背包空间就是一个长度为n的数组,然后容量为1的物体放一个格子,容 ...
- CodeForces B. The least round way(dp)
题目链接:http://codeforces.com/problemset/problem/2/B B. The least round way time limit per test 5 secon ...
- codeforces 459 E. Pashmak and Graph(dp)
题目链接:http://codeforces.com/contest/459/problem/E 题意:给出m条边n个点每条边都有权值问如果两边能够相连的条件是边权值是严格递增的话,最长能接几条边. ...
- codeforces 486 E. LIS of Sequence(dp)
题目链接:http://codeforces.com/contest/486/problem/E 题意:给出n个数,如果一个数满足不属于最长递增序列,那么输出1,如果属于最长递增序列但是不属于所有最长 ...
随机推荐
- C++ 类继承 笔记(初步)
本节内容源于对C++ primer第13章的学习,这本书把C++的原理将得明明白白.网上的博客往往讲得一头雾水.到头来还不如看原书本. 问题 首先给出一题: #include<stdio.h&g ...
- GPIO位带操作点亮LED,且使用按键控制开关
1. 项目 类似与C51单片机的位操作使能引脚来点亮LED. 例如,sbit P0^0 = 0 LED1 = P0^0; 2. 代码 main.c #include "stm32f10x.h ...
- Java中的函数式编程(三)lambda表达式
写在前面 lambda表达式是一个匿名函数.在Java 8中,它和函数式接口一起,共同构建了函数式编程的框架. lambda表达式乍看像是匿名内部类的一种语法糖,但实际上,它们是两种本质不同的事物 ...
- Less-(5~7) error based
Less-5: 核心语句: 我们注意到,当输入正确时,并不能获得有价值的回显.好在出现错误时,会爆出错误内容: 于是,使用报错注入: 1' and updatexml(1,concat(0x7e,( ...
- vue3.x组件间通信,实用小技巧都在这里
本想简单写写,没想到说清楚已经变成了一篇很长的帖子,欢迎当笔记搜藏起来. props / emits 父子组件通信 props一般负责向子组件传递数据 下面是一个简单的例子,父组件向子组件传递了一个t ...
- jQuery实现打开网页自动弹出遮罩层或点击弹出遮罩层功能示例
本文实例讲述了jQuery实现打开网页自动弹出遮罩层或点击弹出遮罩层功能.分享给大家供大家参考,具体如下: 弹出层:两种方式 一是打开网页就自动弹出层二是点击弹出 <!DOCTYPE html ...
- atcoder ABC233
B 题意 给一个字符串, 可以把第一个字母移到最后, 也可以把最后一个字母放第一个, 问字典序最大最小的字符串. 题解 把第一个放最后一个, 相当于把最后一个放第一个执行n-1次, 那么我们不妨只进行 ...
- Code Runner for VS Code,下载量突破 3000 万!
还记得五年前的夏天,我在巨硬写着世界上最好的语言,有时也需要带着游标卡尺写着另一门语言.然而,我对这两门语言都不熟悉,如果能在 VS Code 中方便快捷地运行各种语言,那岂不是很方便?于是,我就开发 ...
- 攻防世界 WEB 高手进阶区 PHP2 Writeup
攻防世界 WEB 高手进阶区 PHP2 Writeup 题目介绍 题目考点 url 二次解码 index.phps 文件(第一次使用dirsearch可能扫不到,需要加到工具字典里) php 简单语法 ...
- Linux配置2个Tomcat同时运行
先说一下怎么遇到的这个问题,在练习linux中部署web项目时,linux系统安装了两个tomcat. 操作步骤: 1.配置profile#vi /etc/profile 输入以下内容: 这是两个to ...