链接:https://www.nowcoder.com/acm/contest/129/C
来源:牛客网
异或和
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制: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字符串。
输出描述:
输出一个整数表示答案模 109
+7
示例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确实需要系统的学习>>要不你就是有系统的学习要不你就得拼刷题量..