HDU 6052 To my boyfriend(概率 贡献)

To my boyfriend

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1246    Accepted Submission(s): 556

Problem Description
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
Input
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).
Output
Each case outputs a number that holds 9 decimal places.
Sample Input
1 2 3 1 2 1 2 1 2
Sample 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)
Source
【题意】给你一个矩阵,求子矩阵中颜色种类数的期望。
【分析】考虑算每一个位置的贡献,然后现在就要定一个提供贡献的规则,假设提供贡献的该种颜色是该子矩阵中该种颜色分布的左上  方,那么只需算出包括这个点的有效子矩阵个数即可。
 
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e2+50;;
const int M = 255;
const int mod = 19260817;
const int mo=123;
const double pi= acos(-1.0);
typedef pair<int,int>pii;
int n,m;
int a[N][N];
int l[N],r[N],pos[N][N*N];
ll ans;
void solve(int x,int y,int col){
    int ly=0,ry=m+1;
    for(int i=1;i<=n;i++)l[i]=0,r[i]=m+1;
    for(int i=1;i<y;i++)l[pos[i][col]]=i;
    for(int i=m;i>y;i--)r[pos[i][col]]=i;
    for(int i=x;i>pos[y][col];i--){
        ly=max(ly,l[i]);
        ry=min(ry,r[i]);
        ans+=(ll)(n-x+1)*(ry-y)*(y-ly);
    }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        met(pos,0);ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                solve(i,j,a[i][j]);
                pos[j][a[i][j]]=i;
            }
        }
        ll all=(ll)n*(n+1)*m*(m+1)/4;
        printf("%.9f\n",(double)ans/all);
    }
    return 0;
}

 

posted @ 2017-09-19 17:19  贱人方  阅读(205)  评论(0编辑  收藏  举报