【GDOI2020模拟4.11】赢家(winner) (计数dp+容斥)
时间:2020-04-11
本文章向大家介绍【GDOI2020模拟4.11】赢家(winner) (计数dp+容斥),主要包括【GDOI2020模拟4.11】赢家(winner) (计数dp+容斥)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述:
PinkRabbit 是一位人赢。
福州市可以抽象成一个n个点m条边的,不包含重边与自环的无向图,PinkRabbit 住在1号
点,而他的妹子住在2号点。
某一天,PinkKitten 施放了一个大魔法,让这个无向图上所有的边都变成了单向边。现在
PinkRabbit 关心的是他是否能够和他的妹子见面。
具体地,PinkRabbit 能和他的妹子见面,当且仅当存在一个点 u,满足新图上从1号点出发能够
到达u,从2号点出发也能到达 。
现在你需要计算出,在把所有 m条边进行定向的所有2^m 种方案中,有多少种方案能让
PinkRabbit 和他的妹子见面。你只需输出其对10^9+7 取模后的结果。
\(n\le 15\)
https://gmoj.net/senior/#main/show/6554
失智了,居然写了个完完全全的dp,还过了样例,然后WA0.
考虑用总方案-不合法方案。
对于不合法方案,枚举1能走到的点集是\(S\),2能走到的点集是\(T\),\(S∩T=∅\)。
设\(Z=总集-S-T\)
那么\(Z\)和\(S、T\)之间的边方向确定,\(S\)和\(T\)之间不能有边。
现在就是求\(S\)的方案数(\(T\)同理)。
设\(f[S]\)表示\(S\)的方案数,同样用总-不合法。
不合法就是是\(S\)的一个子集\(S'\),\(f[S]-=f[S']*(S'和S-S'中间的边定向)\)
预处理\(cnt[S]\)表示S内的边数就都可以快速计算了。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int mo = 1e9 + 7;
const int N = 16;
int n, m, id, x, y;
int b[N][N];
int cnt[1 << 15];
ll a2[N * N];
ll f[1 << 15], g[1 << 15];
int main() {
freopen("winner.in", "r", stdin);
freopen("winner.out", "w", stdout);
scanf("%d %d %d", &n, &m, &id);
fo(i, 1, m) scanf("%d %d", &x, &y), b[x][y] = b[y][x] = 1;
a2[0] = 1; fo(i, 1, n * n) a2[i] = a2[i - 1] * 2 % mo;
ff(s, 0, 1 << n) {
fo(i, 0, n - 1) if(s >> i & 1) {
cnt[s] = cnt[s ^ (1 << i)];
fo(j, 0, n - 1) if(s >> j & 1)
cnt[s] += b[i + 1][j + 1];
break;
}
}
ff(s, 1, 1 << n) {
if(s & 1) {
f[s] = a2[cnt[s]];
for(int t = (s - 1) & s; t > 0; t = (t - 1) & s)
f[s] = (f[s] - f[t] * a2[cnt[s ^ t]]) % mo;
}
if(s & 2) {
g[s] = a2[cnt[s]];
for(int t = (s - 1) & s; t > 0; t = (t - 1) & s)
g[s] = (g[s] - g[t] * a2[cnt[s ^ t]]) % mo;
}
}
ll ans = a2[m];
ff(s, 0, 1 << n) if(f[s]) {
for(int t = s + 1; t < (1 << n); t = (t + 1) | s) if(g[s ^ t]) {
int z = (1 << n) - 1 - t;
if(cnt[s ^ z] + cnt[s ^ t ^ z] - cnt[z] == m) {
ans = (ans - f[s] * g[s ^ t] % mo * a2[cnt[z]]) % mo;
}
}
}
ans = (ans % mo + mo) % mo;
pp("%lld\n", ans);
}
原文地址:https://www.cnblogs.com/coldchair/p/12680071.html
- android自定义view实现公章效果
- ios app url scheme跳转到淘宝商品详情页 唤醒app
- ThreadPoolExecutor运行机制
- Spring Cloud构建微服务架构:服务容错保护(Hystrix依赖隔离)【Dalston版】
- UIPickView的简单使用
- java开发中几种常见的线程池
- 传统多线程之前如何共享数据
- Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)【Dalston版】
- 调整渐变下降的学习率
- 多线程之传统多线程
- ios 常用的正则表达式(手机号邮箱md5加密验证空字符串等)
- Spring Cloud构建微服务架构:Hystrix监控面板【Dalston版】
- 云原生应用的12要素
- Universal-Image-Loader源码分析,及常用的缓存策略
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法