To my boyfriend
2017-08-03 10:52
429 查看
To my boyfriend
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 969 Accepted Submission(s): 446
[align=left]Problem Description[/align]
Dear Liao
I never forget the moment I met with you. You carefully asked me: "I have a very difficult problem. Can you teach me?". I replied with a smile, "of course". You replied:"Given a matrix, I randomly choose a sub-matrix, what is the expectation of the number of
**different numbers** it contains?"
Sincerely yours,
Guo
[align=left]Input[/align]
The first line of input contains an integer T(T≤8) indicating the number of test cases.
Each case contains two integers, n and m (1≤n, m≤100), the number of rows and the number of columns in the grid, respectively.
The next n lines each contain m integers. In particular, the j-th integer in the i-th of these rows contains g_i,j (0≤ g_i,j < n*m).
[align=left]Output[/align]
Each case outputs a number that holds 9 decimal places.
[align=left]Sample Input[/align]
1
2 3
1 2 1
2 1 2
[align=left]Sample Output[/align]
1.666666667
Hint
6(size = 1) + 14(size = 2) + 4(size = 3) + 4(size = 4) + 2(size = 6) = 30 / 18 = 6(size = 1) + 7(size = 2) + 2(size = 3) + 2(size = 4) + 1(size = 6)
题意:
给出一个n*m的矩阵,每个1*1的小矩阵中都有一个数字,现在求大矩阵中所有的矩阵所包含的数字种类和,再除以所有的矩阵数,求数字的期望。
思路:
我们假设一个数字代表一种颜色,便于下面描述。
首先介绍一种求大矩阵中所有矩阵个数的方法。
一个n*m的矩阵,它所包含的所有矩阵个数为:
int total=0; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) total=total+i*j;
此公式代表,以(i,j)这个小矩阵块为右下角的矩阵共有多少个,即从前i行中找一行作为大矩阵的上边,从前j列中找一列作为大矩阵的左列,这样所形成的大矩阵有多少种,即C(i,1)*C(j,1)即i*j。遍历矩阵的每一个1*1小矩阵,就可得n*m的矩阵总个数。
下面介绍如何求出大矩阵中所有的矩阵所包含的颜色种类和。我们以一种颜色为例,这种颜色对答案的贡献为,所有包含这种颜色的矩形个数。我们遍历这种颜色的每一个1*1小矩阵,找出包含这个小矩阵的所有矩阵,就可以得出这个小矩阵对答案的贡献,再遍历所有该颜色的小矩阵,相加就可以得出该颜色对答案的贡献。但是这样直接算会产生重复。所以我们探讨消除这种重复的方法。
首先,我们遍历时找的是,有多少个矩阵包含这个小矩阵,也就是说,有多少个矩阵至少包含一种这样的颜色,现在我们只要保证每次遍历都不与之前的重复,我们就可以消除重复。所以我们定义一种模式,即遍历每一个1*1小矩阵时,我们只能包含这个小矩阵以下,以右的同颜色矩阵,而这个小矩阵以左,以上的同颜色矩阵不再包含,这样就可以实现每次计算时都不重复。这样我们就转化成为寻找边界,即为寻找遍历该小矩阵时,我们所能计算的矩阵的边界。我们在之前定义的方法的限制下,找到每一个小矩阵所形成的上边界,下边界,左边界,有边界,其中这四条边界每一条都是不固定的。其中,由于上边界和下边界的取值范围固定,(设该小矩阵的位置是(x,y),则上边界的取值范围是1到x,下边界的取值范围是x到n),所以我们主要是通过枚举上边界,去限制左右边界。如何找边界及找到边界如何计算详见代码注释。
下面贴上代码:(具体实现过程详见注释)
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAXN=105; int n, m; int color[MAXN][MAXN]; int count(int x, int y) { LL ans=0; int c=color[x][y]; //c是颜色号 int L=1,R=m; //左边界初始化为1,右边界为m for (int i=x; i>=1; i--) //把每一次上边界确定为i,根据上边界限制左右边界 { if (i<x && color[i][y]==c) break; //遍历到第i行,若i<x && color[i][y]==c则说明[x][y]的正上方有一个同颜色的矩阵 //此时无论我们怎样确定左右边界,由于下边界为x到n,我们所得出的矩阵都一定会包含[i][y]这个矩阵 //而根据记下记右,不记上不记左的原则,我们不应包含[i][y]这个小矩阵,所以直接break int l=y,r=y; //左右边界均从当前列的位置左右移动 for (int j=y-1; j>=max(1,L); j--) { if (color[i][j]==c) //从当前列数向左找,找到i行第一个同颜色的方块,记录下左边界 break; l=j; } L=max(L,l); if (i==x) //如果i为当前行,(即上边界为x),则只需要找左边界,右边界为m(因为可以包括右边和下边的相同颜色方块) { ans=ans+(LL)(n-x+1LL)*(y-L+1LL)*(R-y+1LL); continue; } for (int j=y+1; j<=min(m,R); j++) { if (color[i][j]==c) //从当前列数向右找,找到i行第一个同颜色的方块,记录下右边界 break; r=j; } R=min(R,r); ans=ans+(LL)(n-x+1LL)*(y-L+1LL)*(R-y+1LL); //这个公式代表,从x到n中选取一行作为所选矩形的下边,所选矩形的上边为第i行 //从L到y中选一列作为所选矩形的左边,从y到R中选一列作为矩形的右边 //四条线所圈出的矩形就是所选矩形 } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) scanf("%d",&color[i][j]); LL ask=0,total=0; for (int i=1; i<=n; i++) { for (int j=1; j<=m; j++) { ask=ask+count(i,j); total=total+i*j; //计算n*m矩阵有多少个小矩阵,简单算法 } } printf("%.9f\n",ask*1.0/total); } return 0; }
相关文章推荐
- HDU-6052 To my boyfriend 思维
- To my boyfriend HDU - 6052 多校第二场
- hdu6052 To my boyfriend (枚举计数)
- HDU 6052 To my boyfriend 思维 + 枚举(计数)
- HDU-6052 To my boyfriend 思维
- hdu 6052 To my boyfriend(枚举+容斥)
- HDU 6052 2017 Multi-University Training Contest - Team 2 1008 To My Boyfriend:计数问题
- HDU 6052 To my boyfriend 期望 计数
- 17暑假多校联赛2.8 HDU 6052 To my boyfriend
- HDU_【2017 Multi-University Training Contest 2】——1008 To my boyfriend
- HDU6052-To my boyfriend
- (2017多校训练第二场)HDU - 6052 To my boyfriend 思维题
- HDU 6052 To my boyfriend
- 2017 Multi-University Training Contest - Team 2 To My Boyfriend
- 第二场 hdu 6052 To my boyfriend
- HDU-6052 To my boyfriend 思维
- HDU 6052 To my boyfriend(容斥+单调栈)
- HDU-6052 To my boyfriend 思维
- 2017 Multi-University Training Contest - Team 2 :To my boyfriend
- hdu6052 To my boyfriend 枚举