1. 程式人生 > >hdu 6052(暴力枚舉 容斥)

hdu 6052(暴力枚舉 容斥)

ios blog math const href tail sdn target light

思路來自 http://blog.csdn.net/u014258433/article/details/76223343

我是用滑動窗口實現的。

代碼:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
const int maxn = 100;
const long long mod = 1000000007;
int a[maxn + 10][maxn + 10];
int pre[maxn * maxn + 10][maxn + 10];
long long dp[maxn + 10][maxn + 10];
int main()
{
    for(int i = 1; i <= maxn; ++i)
    {
        for(int j = 1; j <= maxn; ++j)
        {
            if(i == 1 && j == 1)
                dp[i][j] = 1;
            else if(i == 1)
                dp[i][j] = dp[i][j - 1] + j;
            else if(j == 1)
                dp[i][j] = dp[i - 1][j] + i;
            else
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + i * j;
        }
    }
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        memset(pre, 0, sizeof(pre));
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= m; ++j)
            {
                scanf("%d", &a[i][j]);
            }
        }
        long long ans = 0;
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= m; ++j)
            {
                int color = a[i][j];
                int l = j, r = j;
                int MAX = pre[color][j];
                ans += (long long)(i - MAX) * (n - i + 1);
                while(l - 1 > 0 && pre[color][l - 1] != i || r + 1 <= m)
                {
                    if(l - 1 > 0 && pre[color][l - 1] != i && r + 1 <= m)
                    {
                        int tmp1 = max(pre[color][l - 1], MAX), tmp2 = max(pre[color][r + 1], MAX);
                        if(tmp1 < tmp2)
                        {
                            ans += (long long)(i - tmp1) * (j - l + 2) * (n - i + 1) * (r - j + 1) - (long long)(i - tmp1) * (j - l + 1) * (n - i + 1) * (r - j + 1);
                            --l;
                            MAX = tmp1;
                        }
                        else
                        {
                            ans += (long long)(i - tmp2) * (j - l + 1) * (n - i + 1) * (r - j + 2) - (long long)(i - tmp2) * (j - l + 1) * (n - i + 1) * (r - j + 1);
                            ++r;
                            MAX = tmp2;
                        }
                    }
                    else if(l - 1 > 0 && pre[color][l - 1] != i)
                    {
                        int tmp = max(pre[color][l - 1], MAX);
                        ans += (long long)(i - tmp) * (j - l + 2) * (n - i + 1) * (r - j + 1) - (long long)(i - tmp) * (j - l + 1) * (n - i + 1) * (r - j + 1);
                        --l;
                        MAX = tmp;
                    }
                    else
                    {
                        int tmp = max(pre[color][r + 1], MAX);
                        ans += (long long)(i - tmp) * (j - l + 1) * (n - i + 1) * (r - j + 2) - (long long)(i - tmp) * (j - l + 1) * (n - i + 1) * (r - j + 1);
                        ++r;
                        MAX = tmp;
                    }
//                    cout << "l == " << l << " r == " << r << endl;
//                    cout << "cur_ans == " << ans << endl;
                }
//                cout << "l == " << l << " r == " << r << endl;
//                cout << "ans == " << ans << endl;
                pre[color][j] = i;
            }
        }
        printf("%.9f\n", ans * 1.0 / dp[n][m]);
    }
    return 0;
}

  

hdu 6052(暴力枚舉 容斥)