牛客挑战赛18 C异或和 (加深下对哈曼顿距离的理解)

链接: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确实需要系统的学习>>要不你就是有系统的学习要不你就得拼刷题量..

猜你喜欢

转载自www.cnblogs.com/vainglory/p/9218849.html