HDU 4917 Permutation
意甲冠军:
序列p1、p2、p3……pn由1、2、3……n这些数字 现在给出一些条件pi<pj 部条件的排列的个数
思路:
非常easy想到用一条有向的线连接全部的pi和pj 那么就构成了有向无环图(题中说有解所以无环)
又由于pi各不同样 那么题目就变成了有向无环图的拓扑排序的种类数
题目中边数较少 所以可能出现不连通情况 我们先讨论一个连通集合内拓扑排序的种类数
题目中m较小 能够利用状压后的记忆化搜索解决
如今考虑假设知道了A和B两个集合各自的种类数 假设把它们合起来
因为各自种类已知 我们能够把A和B当成有序的排列 那么问题就变成了将|B|个元素插空到|A|个元素中间
这个能够利用dp解决 同一时候n较小 我们能够直接打出表
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 45
typedef long long LL; const int mod = (int) 1e9 + 7;
int dp[2][N], f[N][N], in[N], out[N], fa[N], vis[N], qu[N], g[1 << 21];
vector<int> ed[N];
int n, m, ans, top;
struct node {
int id, fa;
bool operator<(const node ff) const {
return fa < ff.fa;
}
} nd[N]; void init() {
for (int i = 1; i <= n; i++) {
in[i] = out[i] = 0;
fa[i] = i;
vis[i] = 0;
ed[i].clear();
}
ans = 1;
top = 0;
} int getf(int x) {
if (x != fa[x])
fa[x] = getf(fa[x]);
return fa[x];
} LL topo(int sta) {
if (g[sta] != -1)
return g[sta];
LL res = 0;
int i, u, j, ss;
for (i = 0; i < top; i++) {
u = qu[i];
if (!vis[u] && !in[u]) {
vis[u] = 1;
ss = ed[u].size();
for (j = 0; j < ss; j++)
in[ed[u][j]]--;
res += topo(sta | (1 << i));
vis[u] = 0;
for (j = 0; j < ss; j++)
in[ed[u][j]]++;
}
}
return g[sta] = res % mod;
} void maketable() {
int i, j, u, v, from, to;
for (i = 1; i < N; i++) {
f[0][i] = 1;
for (j = i; j < N; j++) {
for (v = 1; v <= i + 1; v++)
dp[1][v] = 1;
to = 1;
for (u = 2; u <= j; u++) {
from = (u & 1) ^ 1;
to = u & 1;
for (v = 1; v <= i + 1; v++)
dp[from][v] = (dp[from][v] + dp[from][v - 1]) % mod;
for (v = 1; v <= i + 1; v++)
dp[to][v] = dp[from][v];
}
for (v = 1; v <= i + 1; v++)
dp[to][v] = (dp[to][v] + dp[to][v - 1]) % mod;
f[j][i] = f[i][j] = dp[to][i + 1];
}
}
} int main() {
int i, j, u, v;
maketable();
while (~scanf("%d%d", &n, &m)) {
init();
for (i = 1; i <= m; i++) {
scanf("%d%d", &u, &v);
if (u == v)
continue;
ed[u].push_back(v);
in[v]++;
out[u]++;
u = getf(u);
v = getf(v);
if (u != v)
fa[v] = u;
}
for (i = 1; i <= n; i++) {
nd[i].id = i;
nd[i].fa = getf(i);
}
sort(nd + 1, nd + n + 1);
nd[n + 1].fa = -1;
for (i = 1; i <= n; i = j) {
top = 1;
qu[0] = nd[i].id;
for (j = i + 1; j <= n + 1; j++) {
if (nd[j].fa == nd[i].fa) {
qu[top++] = nd[j].id;
} else {
for (u = 0; u < (1 << top); u++)
g[u] = -1;
g[(1 << top) - 1] = 1;
ans = (LL) ans * (topo(0) * f[i - 1][j - i] % mod) % mod;
break;
}
}
}
printf("%d\n", ans);
}
return 0;
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。
HDU 4917 Permutation的更多相关文章
- HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)
题目链接 Permutation 题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数. 数据规模为n <= 40,m <= 20. 直接状压DP空 ...
- HDU 4917 Permutation 拓扑排序的计数
题意: 一个有n个数的排列,给你一些位置上数字的大小关系.求合法的排列有多少种. 思路: 数字的大小关系可以看做是一条有向边,这样以每个位置当点,就可以把整个排列当做一张有向图.而且题目保证有解,所以 ...
- HDU 5753 Permutation Bo (推导 or 打表找规律)
Permutation Bo 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5753 Description There are two sequen ...
- hdu 5753 Permutation Bo 水题
Permutation Bo 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5753 Description There are two sequen ...
- HDU 3811 Permutation 状压dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3811 Permutation Time Limit: 6000/3000 MS (Java/Othe ...
- HDU 6628 permutation 1 (暴力)
2019 杭电多校 5 1005 题目链接:HDU 6628 比赛链接:2019 Multi-University Training Contest 5 Problem Description A s ...
- hdu 2583 permutation
permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 4345 Permutation dp
Permutation Problem Description There is an arrangement of N numbers and a permutation relation that ...
- hdu 5753 Permutation Bo
这里是一个比较简单的问题:考虑每个数对和的贡献.先考虑数列两端的值,两端的摆放的值总计有2种,比如左端:0,大,小:0,小,大:有1/2的贡献度.右端同理. 中间的书总计有6种可能.小,中,大.其中有 ...
随机推荐
- UVA 11490 - Just Another Problem(数论)
11490 - Just Another Problem option=com_onlinejudge&Itemid=8&page=show_problem&category= ...
- Android获取SIM卡信息--TelephonyManager
1>获得TelephonyManager TelephonyManager telMgr = (TelephonyManager) getSystemService(TELEPHONY_SER ...
- discuz 插件开发 新手入门
作为一个新手,目前也是刚刚玩转discuz的插件功能,好东西不敢独享,就拿出来大家一起分享入门的过程.现在网上很多关于discuz的插件教程都是很简单的教程,原因可能是这个东西是商业化的东西,本着分享 ...
- jdbc初步(转)
1. Jdbc的六个编程步骤 1. 注册一个驱动 注册驱动程序有三种方式: 方式一:Class.forName(“oracle.jdbc.driver.OracleDriver”); JAVA 规范中 ...
- Wake-On-LAN待机或休眠模式中唤醒
Wake-On-LAN简称WOL,是一种电源管理功能:如果存在网络活动,则允许设备将操作系统从待机或休眠模式中唤醒.许多主板厂商支持IBM提出的网络唤醒标准.该标准允许网络管理员远程打开PC机电源,以 ...
- mmc生产任务分配问题
mmc生产任务分配问题,本题目简单.
- 王立平--Failed to push selection: Read-only file system
往android模拟器导入资源,失败. 提示:仅仅读文件. mnt是仅仅读文件.应点击sdcard.,在导入
- C 一个字符串有三段,第一段原样输出,第二段为要输出字符串的长度,第三段为依据第二段长度补齐第一段
C 一个字符串有三段,第一段原样输出.第二段为要输出字符串的长度,第三段为依据第二段长度补齐第一段 比如:输入abc 11 12.输出abc12121212 #include<stdio.h&g ...
- poj Optimal Milking
Optimal Milking 题目: 有K个机器.C仅仅牛.要求求出最全部牛到各个产奶机的最短距离.给出一个C+K的矩阵,表示各种标号间的距离. 而每一个地方最多有M仅仅牛. 算法分析: 二分+最短 ...
- C++转让Lua
转载请注明出处:http://blog.csdn.net/zhy_cheng/article/details/39756423 我使用的cocos2d-x版本号是2.3.3.先在一个C++projec ...