HDU - 6513 Reverse It (SYSU校赛C题)(组合数学+容斥)

题目链接

题意:给定一个n*m的矩阵,可以选择至多两个子矩阵将其反转,求能形成多少种不同的矩阵。

任选一个矩阵有$C_{n+1}^{2}C_{m+1}^{2}$种方法,任选两个不同的矩阵有$C_{C_{n+1}^{2}C_{m+1}^{2}}^{2}$种方法,但其中有重复的,需要去重。

重复的情况一共有以下四种:

第一种,两矩阵拼合成一个矩阵,这样的图形有$C_{n+1}^{2}C_{m+1}^{2}$个,重复度(出现的次数)为(n+m-2)

第二种,形成的两个矩阵在同一行或同一列,有$C_{n+1}^{4}C_{m+1}^{2}+C_{n+1}^{2}C_{m+1}^{4}$个(任选四行两列或两行四列)

第三种,L字形,有$4C_{n+1}^{3}C_{m+1}^{3}$个(任选三行三列+四种位置)

第四种,两矩阵对角,有$2C_{n+1}^{3}C_{m+1}^{3}$个(同上)

第二、三、四种的重复度均为3。

其余情况的重复度为1。

最后还要加上原矩阵的贡献,即答案要加上1。

所以答案为$C_{C_{n+1}^{2}C_{m+1}^{2}}^{2}-(n+m-3)C_{n+1}^{2}C_{m+1}^{2}-2(C_{n+1}^{4}C_{m+1}^{2}+C_{n+1}^{2}C_{m+1}^{4}+6C_{n+1}^{3}C_{m+1}^{3})+1$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll n,m;
 5 ll C(ll n,ll m) {ll ret=1; for(ll i=1; i<=m; ++i)ret=ret*(n-i+1)/i; return ret;}
 6 int main() {
 7     while(scanf("%lld%lld",&n,&m)==2) {
 8         printf("%lld\n",C(C(n+1,2)*C(m+1,2),2)-(C(n+1,3)*C(m+1,3)*6+C(n+1,4)*C(m+1,2)+C(n+1,2)*C(m+1,4))*2-C(n+1,2)*C(m+1,2)*(n+m-3)+1);
 9         while(n--)scanf("%*s");
10     }
11     return 0;
12 }

 

posted @ 2019-04-22 21:58  jrltx  阅读(469)  评论(0编辑  收藏  举报