【多校训练】hdu 6052 To my boyfriend 计数

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)

题意:

给出一个n*m(1<=n,m<=100)的矩阵,每个矩阵元素有一个颜色值ai(0<=ai<=10000),现在定义一个子矩阵的value为子矩阵中不同颜色的数量,求子矩阵value的期望


思路:

这类计数题一般都是考虑每种颜色的贡献值,以及每个点的边界。

枚举每种颜色,单独枚举其中的每个点。考虑这个点的可以生成矩阵的上下左右边界,然后计算贡献。

推荐一篇讲的十分详细的博客:http://blog.csdn.net/calabash_boy/article/details/76272704

具体看代码:

//
//  main.cpp
//  6052
//
//  Created by zc on 2017/9/4.
//  Copyright © 2017年 zc. All rights reserved.
//

#include <iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#define ll long long 
using namespace std;
const int N=110;
int n,m,mp[N][N];
vector<pair<int,int> >r[N*N];
bool v[N][N];

int main(int argc, const char * argv[]) {
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n*m;i++) r[i].clear();
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                scanf("%d",&mp[i][j]);
                r[mp[i][j]].push_back(make_pair(i,j));
            }
        for(int i=0;i<=n*m;i++)
            if(!r[i].empty())
                sort(r[i].begin(),r[i].end());
        ll ans=0;
        for(int col=0;col<=n*m;col++)
        {
            if(r[col].empty())   continue;
            memset(v,0,sizeof(v));
            for(int i=0;i<r[col].size();i++)
            {
                pair<int,int> t=r[col][i];
                int x=t.first,y=t.second;
                for(int j=x;j>=0&&v[j][y]==0;j--)
                {
                    int l,r;
                    for(l=y;l>=0&&v[j][l]==0;l--);
                    for(r=y;r<m&&v[j][r]==0;r++);
                    ans+=(ll)(n-x)*(y-l)*(r-y);
                    v[j][y]=1;
                }
            }
        }
        printf("%.9f\n",(double)ans/(n*(n+1)*m*(m+1)/4));
    }
}

发布了323 篇原创文章 · 获赞 119 · 访问量 21万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章