题目传送门

  传送点

题目大意

  给定$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 - 动态规划 - 组合数学相关推荐

  1. CF 979E Kuro and Topological Parity

    Kuro and Topological Parity 题目描述 传送门:http://codeforces.com/contest/979/problem/E 题解 题目要求确定节点的颜色,使得黑白 ...

  2. CodeForces - 1000D Yet Another Problem On a Subsequence(动态规划+组合数学)

    题目链接:点击查看 题目大意:给出n个数字组成的序列,现在规定"好数组"指的是一个连续序列a1,a2,...ak的a1=k-1,再规定"好序列"是可以分为若干个 ...

  3. Codeforces Beta Round #10 D. LCIS 动态规划

    D. LCIS 题目连接: http://www.codeforces.com/contest/10/problem/D Description This problem differs from o ...

  4. [POJ1664] 放苹果 (动态规划,组合数学)

    题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分发(5,1,1和1,1,5是同一种方法) 输入输出格式 输入格式: 第一行是测试数据的数目t(0 <= ...

  5. CodeForces - 894B Ralph And His Magic Field(组合数学+思维)

    题目链接:点击查看 题目大意:给出一个 n * m 的棋盘,需要在棋盘内填充数字,使得每一行.每一列的乘积都等于 k,问有多少种方案 题目分析:因为 k 只可能是 1 或 -1,所以在棋盘内填充的数字 ...

  6. CodeForces - 979D Kuro and GCD and XOR and SUM(字典树+暴力+模拟)

    题目链接:点击查看 题目大意:说实话看到这么复杂而且还是英文的题面我是拒绝的,但题还是得补啊,就去百度找的题解看题意,题意大概是这样的: 给出n个操作,每个操作分为两种类型: 1 x:向集合中插入x ...

  7. *【CodeForces - 214D 】Numbers (dp,组合数学)

    题干: Furik loves writing all sorts of problems, especially such that he can't solve himself. You've g ...

  8. 【Codeforces 869 C The Intriguing Obsession】 组合数学 思维

    C. The Intriguing Obsession time limit per test1 second memory limit per test256 megabytes inputstan ...

  9. Codeforces 869 C. The Intriguing Obsession (组合数学)

    Description With hands joined, go everywhere at a speed faster than our thoughts! This time, the Fir ...

最新文章

  1. 对科大讯飞的过度宽容就是对科大讯飞的伤害,从科大讯飞裁员说起
  2. 【KVM系列03】KVM的I/O 全虚拟化和准虚拟化
  3. 任务31:课时介绍 任务32:Cookie-based认证介绍 任务33:34课 :AccountController复制过来没有移除[Authorize]标签...
  4. VM虚拟机跟主机间共享文件
  5. 敏捷个人: 使用必须、应该、可以来确定每天事情的优先级
  6. 一个长方体玻璃容器从里面量长宽_泰来包装分享:如何设计钢边箱里面中型木包装箱...
  7. C语言试题七十三之请编写函数求两个数的最大公约数
  8. php mysql 查询数据库表结构_mysql查询数据库下的表结构?
  9. python独一无二的路_独一无二的Python基础学习——可用作面试
  10. 5.3 数值分析: 差商的定义及性质
  11. Hi3516A开发--电阻分压阻值计算
  12. SEO面试的一些常见问题整理
  13. EXCEL:SUMIFS多条件求和2(筛选效果),含字符串转数组用法
  14. HashMap中put方法(白话加源码分析)
  15. java连接oracle报错ora-12505,Oracle SQL Developer连接报错(ORA-12505)的解决方案(两种)
  16. 怎么做电商运营?浅谈我的电商之路
  17. ctfshow node.js专题
  18. ELF文件格式, ELF文件是什么,里面包含什么内容
  19. 继Pyecharts之后,蚂蚁又开源一款国产可视化利器
  20. Veryzhou编码转换1.02正式版

热门文章

  1. deepin 20.2 在 vmware 下的安装
  2. Lodop打印图片(工作记录)
  3. 互联网产品设计第一步,账户设计之个人实名认证
  4. Python简单购买苹果案例
  5. ubuntu 修改apache2 默认网站目录和默认主页文档
  6. 酒店餐饮行业短信平台解决方案
  7. iPhone隐藏指令
  8. 我们都是小清新,学习——So easy
  9. Acer宏碁笔记本电脑 暗影骑士 AN515-52原装出厂恢复原厂系统1709
  10. ios 输入法扩展_App Extension编程指南(iOS8/OS X v10.10):扩展类型--自定义键盘