Codeforces 979E Kuro and Topological Parity - 动态规划 - 组合数学
题目传送门
传送点
题目大意
给定$n$个标号依次为$1, 2, \cdots, n$的点,其中一些点被染成一些颜色,剩下的点没有染色。你需要添加一些有向边并将剩下的点染色,满足有向边从编号小的一端指向编号大的一端,图中所有黑白相错的路径的条数与$p$对2取模同余。
$1\leqslant n\leqslant 10^6$
想一下如何求DAG中黑白相错的路径的条数。用$g_{i}$表示$i$结尾的路径的条数。
考虑怎么转移,枚举前一个点,然后$g_{i} += g_{pre}[col_{pre}\neq col_{i}]$。
这里我们希望知道所有点的$g$的和的奇偶性。我们考虑每次加入一个点,我们希望知道它的$g$的奇偶性就能更新了。
它更新的时候的奇偶性只与$g_{pre}$的奇偶性以及$g$的颜色有关,因此我们可以将点分为四类:
- 奇黑点,$g_{p} \equiv 1 \pmod{2} \wedge col_{i} = black$
- 偶黑点,$g_{p} \equiv 0 \pmod{2} \wedge col_{i} = black$
- 奇白点,$g_{p} \equiv 1 \pmod{2} \wedge col_{i} = white$
- 偶白点,$g_{p} \equiv 0 \pmod{2} \wedge col_{i} = white$
然后假设当前的即将加入的点是白点,那么考虑它的连边
- 之前的白点对它的奇偶性没有影响,所以这之间的边可以任意连。
- 偶黑点对它的奇偶性也没有影响,所以这之间的边可以任意连。
- 考虑奇黑点
- 如果不存在奇黑点,那么当前点一定是奇白点(它自己的方案)。
- 如果存在奇黑点,每与一个奇黑点连边就会改变一次奇偶性,那么我们先拿走一个,剩下的任意连,拿走的这一个可以控制这个点方案数的奇偶性(比如考虑这个点之前当前点是奇白点,我希望它是奇白点,那么不连边)。因此恰好一半的任意连边方法使当前点的奇偶性为奇或偶。
对黑点可以作类似的讨论,然后我们可以愉快地得出结论:
- 如果当前不存在方案数为奇数的颜色与当前点相反的点,那么之前方案数乘上$2^{i - 1}$转移到当前点方案数为奇数的状态。
- 否则,对于当前点方案数为奇为偶各加上之前方案数乘$2^{i - 2}$。
状态用$f_{i, have\_odd\_white, have\_odd\_black, parity}$来表示。
时间复杂度$O(n)$。
Code
1 /** 2 * Codeforces 3 * Problem#979E 4 * Accepted 5 * Time: 31ms 6 * Memory: 36100k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const int N = 55, M = 1e9 + 7; 13 14 int add(int a, int b) { 15 a += b; 16 if (a >= M) 17 return a - M; 18 return a; 19 } 20 21 int n, p; 22 int ar[N]; 23 int pow2[N]; 24 int f[N][N][N][N]; 25 int C[N][N]; 26 int Co[N], Ce[N]; 27 28 inline void init() { 29 scanf("%d%d", &n, &p); 30 for (int i = 1; i <= n; i++) 31 scanf("%d", ar + i); 32 } 33 34 inline void prepare() { 35 pow2[0] = 1; 36 for (int i = 1; i <= n; i++) 37 pow2[i] = add(pow2[i - 1], pow2[i - 1]); 38 39 C[0][0] = 1; 40 for (int i = 1; i <= n; i++) { 41 C[i][0] = C[i][i] = 1; 42 for (int j = 1; j < n; j++) 43 C[i][j] = add(C[i - 1][j], C[i - 1][j - 1]); 44 } 45 46 for (int i = 0; i <= n; i++) { 47 for (int j = 0; j <= n; j++) 48 if (j & 1) { 49 Co[i] = add(Co[i], C[i][j]); 50 } else { 51 Ce[i] = add(Ce[i], C[i][j]); 52 } 53 } 54 } 55 56 inline void solve() { 57 f[0][0][0][0] = 1; 58 for (int i = 1; i <= n; i++) 59 // enmuerating last status 60 for (int ob = 0; ob < i; ob++) // odd black 61 for (int eb = 0; ob + eb < i; eb++) // even black 62 for (int ow = 0; ob + eb + ow < i; ow++) { // odd white 63 int lans = f[i - 1][ob][eb][ow]; 64 if (!lans) 65 continue; 66 int ew = i - ob - eb - ow - 1; 67 if (ar[i] != 0) { // here painted in white 68 int gama = pow2[ow + ew + eb]; 69 f[i][ob][eb][ow] = add(f[i][ob][eb][ow], lans * 1ll * gama % M * Co[ob] % M); 70 f[i][ob][eb][ow + 1] = add(f[i][ob][eb][ow + 1], lans * 1ll * gama % M * Ce[ob] % M); 71 } 72 73 if (ar[i] != 1) { // here painted in black 74 int gama = pow2[ew + ob + eb]; 75 f[i][ob][eb + 1][ow] = add(f[i][ob][eb + 1][ow], lans * 1ll * gama % M * Co[ow] % M); 76 f[i][ob + 1][eb][ow] = add(f[i][ob + 1][eb][ow], lans * 1ll * gama % M * Ce[ow] % M); 77 } 78 } 79 80 int res = 0; 81 for (int ob = 0; ob <= n; ob++) 82 for (int eb = 0; eb + ob <= n; eb++) 83 for (int ow = 0; ow + eb + ob <= n; ow++) 84 if (((ob + ow) & 1) == p) 85 res = add(res, f[n][ob][eb][ow]); 86 printf("%d\n", res); 87 } 88 89 int main() { 90 init(); 91 prepare(); 92 solve(); 93 return 0; 94 }
Slower Solution
1 /** 2 * Codeforces 3 * Problem#979E 4 * Accepted 5 * Time: 31ms 6 * Memory: 300k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const int N = 55, M = 1e9 + 7; 13 14 int add(int a, int b) { 15 a += b; 16 if (a >= M) 17 return a - M; 18 return a; 19 } 20 21 int n, p; 22 int ar[N]; 23 int pow2[N]; 24 int f[N][2][2][2]; 25 26 inline void init() { 27 scanf("%d%d", &n, &p); 28 for (int i = 1; i <= n; i++) 29 scanf("%d", ar + i); 30 pow2[0] = 1; 31 for (int i = 1; i <= n; i++) 32 pow2[i] = add(pow2[i - 1], pow2[i - 1]); 33 } 34 35 inline void solve() { 36 f[0][0][0][0] = 1; 37 for (int i = 1; i <= n; i++) 38 // enmuerating last status 39 for (int hob = 0; hob < 2; hob++) // exists odd black or not 40 for (int how = 0; how < 2; how++) // exists odd white or not 41 for (int par = 0; par < 2; par++) { 42 int lans = f[i - 1][hob][how][par]; 43 if (!lans) 44 continue; 45 if (ar[i] != 0) { // here painted in white 46 if (!hob) 47 f[i][0][1][par ^ 1] = add(f[i][0][1][par ^ 1], lans * 1ll * pow2[i - 1] % M); 48 else { 49 f[i][1][1][par ^ 1] = add(f[i][1][1][par ^ 1], lans * 1ll * pow2[i - 2] % M); 50 f[i][1][how][par] = add(f[i][1][how][par], lans * 1ll * pow2[i - 2] % M); 51 } 52 } 53 54 if (ar[i] != 1) { // here painted in black 55 if (!how) 56 f[i][1][0][par ^ 1] = add(f[i][1][0][par ^ 1], lans * 1ll * pow2[i - 1] % M); 57 else { 58 f[i][1][1][par ^ 1] = add(f[i][1][1][par ^ 1], lans * 1ll * pow2[i - 2] % M); 59 f[i][hob][1][par] = add(f[i][hob][1][par], lans * 1ll * pow2[i - 2] % M); 60 } 61 } 62 } 63 int res = 0; 64 for (int x = 0; x < 2; x++) 65 for (int y = 0; y < 2; y++) 66 res = add(res, f[n][x][y][p]); 67 printf("%d\n", res); 68 } 69 70 int main() { 71 init(); 72 solve(); 73 return 0; 74 }
转载于:https://www.cnblogs.com/yyf0309/p/9691101.html
Codeforces 979E Kuro and Topological Parity - 动态规划 - 组合数学相关推荐
- CF 979E Kuro and Topological Parity
Kuro and Topological Parity 题目描述 传送门:http://codeforces.com/contest/979/problem/E 题解 题目要求确定节点的颜色,使得黑白 ...
- CodeForces - 1000D Yet Another Problem On a Subsequence(动态规划+组合数学)
题目链接:点击查看 题目大意:给出n个数字组成的序列,现在规定"好数组"指的是一个连续序列a1,a2,...ak的a1=k-1,再规定"好序列"是可以分为若干个 ...
- Codeforces Beta Round #10 D. LCIS 动态规划
D. LCIS 题目连接: http://www.codeforces.com/contest/10/problem/D Description This problem differs from o ...
- [POJ1664] 放苹果 (动态规划,组合数学)
题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分发(5,1,1和1,1,5是同一种方法) 输入输出格式 输入格式: 第一行是测试数据的数目t(0 <= ...
- CodeForces - 894B Ralph And His Magic Field(组合数学+思维)
题目链接:点击查看 题目大意:给出一个 n * m 的棋盘,需要在棋盘内填充数字,使得每一行.每一列的乘积都等于 k,问有多少种方案 题目分析:因为 k 只可能是 1 或 -1,所以在棋盘内填充的数字 ...
- CodeForces - 979D Kuro and GCD and XOR and SUM(字典树+暴力+模拟)
题目链接:点击查看 题目大意:说实话看到这么复杂而且还是英文的题面我是拒绝的,但题还是得补啊,就去百度找的题解看题意,题意大概是这样的: 给出n个操作,每个操作分为两种类型: 1 x:向集合中插入x ...
- *【CodeForces - 214D 】Numbers (dp,组合数学)
题干: Furik loves writing all sorts of problems, especially such that he can't solve himself. You've g ...
- 【Codeforces 869 C The Intriguing Obsession】 组合数学 思维
C. The Intriguing Obsession time limit per test1 second memory limit per test256 megabytes inputstan ...
- Codeforces 869 C. The Intriguing Obsession (组合数学)
Description With hands joined, go everywhere at a speed faster than our thoughts! This time, the Fir ...
最新文章
- 微信小程序 = 滚动页面
- ASP.NET AJAX入门系列(9):在母版页中使用UpdatePanel
- cc压力测试_斯坦福大学鲍哲南院士AFM综述:教你如何设计压力传感器的微结构...
- 什么是Maven神器?
- oracle服务没有了 原因,一例oracle服务无法启动的原因及解决方法
- 【图像增强】基于matlab区域相似变换函数和蜻蜓算法灰度图像增强【含Matlab源码 089期】
- 推荐一个强大的串口监控软件(免费)
- 计算机用三角函数时如何用弧度制,5.1.2弧度制教学设计
- 解决svn文件图标不显示
- PPT(母版的使用))
- json面试题_JAVA SSM 框架面试题,附答案!
- 位运算符详解(与,或,非,异或)
- C#调用科大讯飞离线语音合成TTS
- python2.7安装手把手教程_手把手windows64位配置安装python2.7
- Android系统手机通讯录
- 网格合并案例:实现网页图片不规则排列的两种办法
- linux下如何将镜像挂载,Linux下挂载本地镜像
- 【C++】一文搞懂C++中的std::是什么
- 计算机直接制版的优势,计算机直接制版技术.ppt
- Centos7篇---Centos7 卸载nvidia驱动和CUDA toolkit
热门文章
- notifyDataSetChanged和notifyDataSetInvalidated区别以及观察者模式的使用
- php中setcookie,php中setcookie() 函数用法介绍
- KILL Linked Server异常中断会话后一直处于KILLED/ROLLBACK状态
- win10 更新失败 循环
- 怎么用小学生计算机玩游戏,小学生如何学习计算机
- CISA Cert Prep: 5 Information Asset Protection for IS Auditors CISA证书准备:5 IS审计员的信息资产保护 Lynda课程中文字幕
- 解决JSP发送到Servlet的字符串产生字符转义的问题
- 名詞解釋 : LTI / CTI / LNR / CNR
- 计算机用户的购买能力,有钱也不能乱花 3类用户不宜买HD4850
- c++中子类和父类的强制转换