1. 程式人生 > >牛客挑戰賽18 C異或和 (加深下對哈曼頓距離的理解)

牛客挑戰賽18 C異或和 (加深下對哈曼頓距離的理解)

coder scanf fin board 貢獻 brush true mat TE

鏈接:https://www.nowcoder.com/acm/contest/129/C
來源:牛客網

異或和 時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

有一個n*m的網格圖,給出小B出現在每個位置的可能性,用一個n*m的01矩陣表示,小B等概率出現在所有1的位置。求小A在每個位置上與小B期望曼哈頓距離的異或和,先把期望取模之後再異或

輸入描述:

第一行讀入兩個整數 n,m (n,m <= 2000)
接下來n行,每行讀入一個長度為m的01字符串。

輸出描述:

輸出一個整數表示答案模 10
9
+7
示例1

輸入

復制
1 3
101

輸出

復制
1

說明

小A出現在(1,1)的時候期望曼哈頓距離是1
小A出現在(1,2)的時候期望曼哈頓距離是1
小A出現在(1,3)的時候期望曼哈頓距離是1
答案是這三者的異或和。
#include<bits/stdc++.h>
#include<cstring>
#define ll long long
using namespace std;
const int maxn = 2e3 + 7;
const ll mod = 1000000007;
ll h[maxn],l[maxn];
int n,m;
char mp[2022][2022];
ll a[maxn], b[maxn], ans, Ans;
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
int main()
{
    ll cnt=0;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        getchar();
        for (int j=1;j<=m;j++)
        {
            mp[i][j]=getchar();
            if (mp[i][j]==‘1‘)
                cnt++,h[i]++,l[j]++;
        }
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            a[j]+=abs(i-j)*h[i];
    for (int i=1;i<=m;i++)
        for (int j=1;j<=m;j++)
            b[j]+=abs(i-j)*l[i];
    ll hh = fpow(cnt,mod-2);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            ans^=(ll)(a[i]+b[j])*hh%mod;
    cout<<ans<<endl;
    return 0;
}

  加深的理解是對於 哈曼頓距離可以分開求x,y>>其次對於同一行的點來說>>哈曼頓距離的貢獻是一樣的

  這個題寫不出來的話,純屬對哈曼頓距離的理解不夠深>>我覺得acm確實需要系統的學習>>要不你就是有系統的學習要不你就得拼刷題量..

牛客挑戰賽18 C異或和 (加深下對哈曼頓距離的理解)