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