意甲冠军:

序列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的更多相关文章

  1. HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)

    题目链接 Permutation 题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数. 数据规模为n <= 40,m <= 20. 直接状压DP空 ...

  2. HDU 4917 Permutation 拓扑排序的计数

    题意: 一个有n个数的排列,给你一些位置上数字的大小关系.求合法的排列有多少种. 思路: 数字的大小关系可以看做是一条有向边,这样以每个位置当点,就可以把整个排列当做一张有向图.而且题目保证有解,所以 ...

  3. HDU 5753 Permutation Bo (推导 or 打表找规律)

    Permutation Bo 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5753 Description There are two sequen ...

  4. hdu 5753 Permutation Bo 水题

    Permutation Bo 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5753 Description There are two sequen ...

  5. HDU 3811 Permutation 状压dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3811 Permutation Time Limit: 6000/3000 MS (Java/Othe ...

  6. HDU 6628 permutation 1 (暴力)

    2019 杭电多校 5 1005 题目链接:HDU 6628 比赛链接:2019 Multi-University Training Contest 5 Problem Description A s ...

  7. hdu 2583 permutation

    permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  8. HDU 4345 Permutation dp

    Permutation Problem Description There is an arrangement of N numbers and a permutation relation that ...

  9. hdu 5753 Permutation Bo

    这里是一个比较简单的问题:考虑每个数对和的贡献.先考虑数列两端的值,两端的摆放的值总计有2种,比如左端:0,大,小:0,小,大:有1/2的贡献度.右端同理. 中间的书总计有6种可能.小,中,大.其中有 ...

随机推荐

  1. c语言来实现c++

    闲来没事,看了看sqlite的源代码,突然想用c实现c++,写了例如以下demo,自我感觉不错 #include <stdio.h> #include <stdlib.h> s ...

  2. 使用SVNkit删除版本库的文件

    源网址:http://wiki.svnkit.com/Committing_To_A_Repository Editing Operation: commiting to a repository T ...

  3. SVN的revert和update命令的区别

    svn中的revert和update 今天有人问到revert和update的问题. 刚开始还真被问住了. 因为感觉revert和update都可以将本地的copy更新到以前的一个版本,会有什么不同呢 ...

  4. onmouseover 执行 ToolTip 控件

    Tooltip控件是一个简单,但非常有用的控件.它能够为我们的软件提供非常漂亮的提示信息,提高软件的可用性,给用户比较好的体验.假设现在有两个按钮,一个用来预览吊线世系图,一个用来预览行转.为了保持按 ...

  5. _tkinter.TclError: no display name and no $DISPLAY environment variable

    _tkinter.TclError: no display name and no $DISPLAY environment variable 这是在使用cocos2d-x的pluginx时遇到的一个 ...

  6. ECLIPSE JSP TOMCAT 环境搭建

    ECLIPSE JSP TOMCAT 环境搭建(完整) 要学习一门语言,首先要做的就是搭建环境,然后能写一个小的Demo(类似Helloworld),不仅可以建立信心,而且还可以为之后的学习搭建一个验 ...

  7. CC2530 外部中断 提醒

    #include "ioCC2530.h" #define uchar unsigned char #define led1    P1_0 #define led2    P1_ ...

  8. 配置jndi服务,javax.naming.NamingException的四种情况

    1.当jndi服务没有启动,或者jndi服务的属性没有设置正确,抛出如下异常: javax.naming.CommunicationException: Can't find SerialContex ...

  9. oracle查询和编写数据字典

    在项目交付时假设须要编写数据字典,能够採用以下的方法.首先执行以下的sql语句 SELECT A.TABLE_NAME AS 表名, A.COLUMN_NAME AS 字段名, DECODE(A.CH ...

  10. 于Unity3D动态创建对象和创建Prefab三种方式的原型对象

    于Unity3D动态创建对象和创建Prefab三种方式的原型对象 u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject o ...