HDU 5729 Rigid Frameworks(组合计数,递推)
来源:互联网 发布:sql server在哪下载 编辑:程序博客网 时间:2024/05/21 20:25
[题目链接]
[题意]
赛上就没读懂过题意…
通过转换将问题变为求两个点集大小分别为n和m的连通二分图个数,其中每条边可以有2种选择(主副对角线)
[分析]
如果每条边只有1种选择,那就变成了Project Euler 434,所以我们先来考虑这个问题
对于n,m点的二分图,若不考虑连通性的限制,那么总方案数为
只要再减去不连通的情况即可
如何不重复不遗漏的计算出不连通的方案数呢?
这里本弱学习了一种看起来十分靠谱的递推方案
设有n,m点的两个点集
从
对于每一种选法,设两个点集剩余部分为
枚举i和j,依次减去即可
但注意到,这样枚举是会有重复计算的
比如,在选取前i个点与前j个点时,对应于取后n-i点和后m-j点,会有重复统计的情况
为了避免这种情况,我们可以在A中固定取第一个点,在剩余的n-1个点中取i-1个点,而B的取法不变,这样做就能做到不重复不遗漏
因为所有不包含A中第一个点的方案都被对称的统计了,而且这样选取是不会出现重复的
在加入边的选择后, 只需要多存一维边数,枚举的时候也多枚举一维边数即可
任意连k条边的方案数为
最终答案为
[代码]
#include <bits/stdc++.h>using namespace std ;const int N = 11 ;const int M = 101 ;const int mod = 1e9 + 7 ;typedef long long LL ;int n , m ;LL f[N][N][M] , p2[M] ;LL C[M][M] ;int ans[N][N] ;void init(){ C[0][0] = p2[0] = 1 ; for( int i = 1 ; i < M ; i++ ) { p2[i] = p2[i-1]*2%mod ; C[i][i] = C[i][0] = 1 ; for( int j = 1 ; j < i ; j++ ) C[i][j] = ( C[i-1][j-1] + C[i-1][j] ) % mod ; } memset(f,-1,sizeof(f)) ;}LL dfs( int n , int m , int k ){ if( n < m ) swap(n,m) ; if( ~f[n][m][k] ) return f[n][m][k] ; LL sum = 0 ; for( int i = 1 ; i <= n ; i++ ) { for( int j = 0 ; j <= m ; j++ ) { if( i == n && j == m ) continue ; for( int s = 0 ; s <= k ; s++ ) { sum += dfs(i,j,s)*C[n-1][i-1]%mod*C[m][j]%mod*C[(n-i)*(m-j)][k-s]%mod ; } } } return f[n][m][k] = ( C[n*m][k] - sum%mod + mod ) % mod ;}int main(){ init() ; while( ~scanf( "%d%d" , &n , &m ) ) { LL ans = 0 ; for( int i = 0 ; i <= n*m ; i++ ) { ans += dfs(n,m,i)*p2[i]%mod ; } printf( "%I64d\n" , ans%mod ) ; } return 0 ;}
[更新]
发现自己简直是zz
根本不需要再加一维边数
每个格子的选择就3种,不连,连主对角线,连副对角线
所以只需要把PE 434 中的
这样之后0ms通过,代码量也少了很多
[代码]
#include <bits/stdc++.h>using namespace std ;const int N = 11 ;const int M = 101 ;const int mod = 1e9 + 7 ;typedef long long LL ;int n , m ;LL f[N][N] , p3[M] ;LL C[M][M] ;int ans[N][N] ;void init(){ C[0][0] = p3[0] = 1 ; for( int i = 1 ; i < M ; i++ ) { p3[i] = p3[i-1]*3%mod ; C[i][i] = C[i][0] = 1 ; for( int j = 1 ; j < i ; j++ ) C[i][j] = ( C[i-1][j-1] + C[i-1][j] ) % mod ; } memset(f,-1,sizeof(f)) ;}LL dfs( int n , int m ){ if( n < m ) swap(n,m) ; if( ~f[n][m] ) return f[n][m] ; LL sum = 0 ; for( int i = 1 ; i <= n ; i++ ) { for( int j = 0 ; j <= m ; j++ ) { if( i == n && j == m ) continue ; sum += dfs(i,j)*C[n-1][i-1]%mod*C[m][j]%mod*p3[(n-i)*(m-j)]%mod ; } } return f[n][m] = ( p3[n*m] - sum%mod + mod ) % mod ;}int main(){ init() ; while( ~scanf( "%d%d" , &n , &m ) ) { printf( "%I64d\n" , dfs(n,m) ) ; } return 0 ;}
- HDU 5729 Rigid Frameworks(组合计数,递推)
- [HDU 5729] Rigid Frameworks (二分图联通方案计数)
- HDU 5729 Rigid Frameworks(组合数学+dp)
- 【HDU 5729】Rigid Frameworks(组合数学+DP)
- hdu 5729 Rigid Frameworks
- HDU 5729 Rigid Frameworks (连通二分图计数DP)
- PE 434 Rigid graphs && HDU 5729 Rigid Frameworks
- hdu Rigid Frameworks(刚体图->二分图计数)
- [二分图] hdu 5729 Rigid Frameworks
- hdu 5279 Rigid Frameworks
- hdu5729 Rigid Frameworks(连通二分图计数dp)
- HDU 5729 Rigid Frameworks (求二分图连通方案数)
- HDU 5729 Rigid Frameworks (from: 2016 Multi-University Training Contest)
- 第二章:数学基础(组合计数+递推)
- 递推,计数(危险的组合,uva 580)
- UVALive 3720 Highways(组合计数、递推)
- HDU 1438 钥匙计数之一 递推+组合 简洁的做法
- 递推计数-hdu-4747-Mex
- The Python Tutorial - Data Structures
- java中转发和重定向的区别
- java进程、线程、多线程以及线程安全问题
- SpringMVC学习笔记
- ubuntu下ssh远程登录
- HDU 5729 Rigid Frameworks(组合计数,递推)
- 杭电ACM中一部分关于string的题目
- Android锁屏状态下弹出activity,如新版qq的锁屏消息提示
- Git入门(5)-工作区和暂存区
- leetcode 150. Evaluate Reverse Polish Notation java 算法
- Codeforces Round #274 (Div. 1) C. Riding in a Lift
- Android 自定义View实现ViewPager指示器
- Android与PC蓝牙交互
- 关于scipy安装运行问题