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). OutputEach case outputs a number that holds 9 decimal places. Sample Input
1 2 3 1 2 1 2 1 2Sample Output
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) 分析:我們考慮計算每種顏色的貢獻和,我們將某個子矩陣中對答案有貢獻的方格定義爲這個子矩陣的所有同色方格中最高上左的那個(先上後左),然後我們再轉來計算每個方格貢獻的子矩陣個數,這個用單調棧可以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)));
}
}