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
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
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).
1 2 3 1 2 1 2 1 2
1.666666667
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) 分析:我们考虑计算每种颜色的贡献和,我们将某个子矩阵中对答案有贡献的方格定义为这个子矩阵的所有同色方格中最高上左的那个(先上后左),然后我们再转来计算每个方格贡献的子矩阵个数,这个用单调栈可以O(n)计算,总复杂度O(n^3).
#include <bits/stdc++.h> #define N 105 using namespace std; typedef long long ll; struct thing { int x,n; thing(){}; thing(int a,int b){x = a,n = b;} }Stack[N]; int T,n,m,tot,c[N][N],pre[N*N][N],Pre[N*N][N],vis[N*N]; ll ans; int Count(int l,int r,int i,int j,int col) { int sum = 0,t = 0,ans = 0; for(int k = l;k <= r;k++) { int d = (i == pre[col][k] && k >= j) ? i - Pre[col][k] : i - pre[col][k]; if(!d) t = sum = 0; else { thing u = thing(d,1); while(t && Stack[t].x >= u.x) { sum -= Stack[t].x*Stack[t].n; u.n += Stack[t].n; t--; } sum += u.x*u.n*1ll; Stack[++t] = u; ans += sum; } } return ans; } int main() { scanf("%d",&T); while(T--) { memset(pre,0,sizeof(pre)); memset(vis,0,sizeof(vis)); tot = 0,ans = 0; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) { scanf("%d",&c[i][j]); if(!vis[c[i][j]]) tot++,vis[c[i][j]] = 1; } for(int i = 1;i <= n;i++) { for(int j = 1;j <= m;j++) { Pre[c[i][j]][j] = pre[c[i][j]][j]; pre[c[i][j]][j] = i; } for(int j = 1;j <= m;j++) { int col = c[i][j]; ans += (n-i+1ll)*(Count(1,m,i,j,col) - Count(1,j-1,i,j,col) - Count(j+1,m,i,j,col)); } } printf("%.9f\n",ans*4.0/(n*(n+1)*m*(m+1))); } }