原题: https://acm.ecnu.edu.cn/contest/113/problem/C/
题意:
01矩阵,
C
o
s
t
(
i
,
j
)
Cost(i,j)
Cost(i,j)为i行和j列的0的个数,
S
u
m
=
∑
i
=
1
n
∑
j
=
1
n
C
o
s
t
(
i
,
j
)
Sum=sum_{i=1}^nsum_{j=1}^nCost(i,j)
Sum=∑i=1n∑j=1nCost(i,j)
每次操作为反转一个位置的数,求开始的Sum和每次操作后的Sum
解析:
设
R
i
R_i
Ri为i行的0数量,
C
j
C_j
Cj为j列的0数量,
B
i
j
B_{ij}
Bij表示ij位置是否为0,
A
A
A为矩阵中0的数量
(
∑
i
=
1
n
B
i
j
=
C
j
,
∑
j
=
1
n
B
i
j
=
R
i
,
∑
i
=
1
n
C
j
=
∑
j
=
1
n
R
i
=
A
sum_{i=1}^nB_{ij}=C_j,sum_{j=1}^nB_{ij}=R_i,sum_{i=1}^nC_{j}=sum_{j=1}^nR_{i}=A
∑i=1nBij=Cj,∑j=1nBij=Ri,∑i=1nCj=∑j=1nRi=A)
那么接下来化简题目表达式:
S
u
m
=
∑
i
=
1
n
∑
j
=
1
n
C
o
s
t
2
(
i
,
j
)
=
∑
i
=
1
n
∑
j
=
1
n
(
R
i
+
C
j
−
B
i
j
)
2
=
∑
i
=
1
n
[
(
R
i
+
C
1
−
B
i
1
)
2
+
…
(
R
i
+
C
n
−
B
i
n
)
2
]
=
∑
i
=
1
n
[
(
R
i
+
C
1
)
2
+
B
i
1
−
2
B
i
1
(
R
i
+
C
1
)
+
…
 
]
=
∑
i
=
1
n
[
(
n
R
i
2
+
(
C
1
2
+
…
C
n
2
)
+
2
R
i
A
)
+
R
i
−
2
R
i
2
−
∑
j
=
1
n
2
B
i
j
C
j
]
Sum=sum_{i=1}^nsum_{j=1}^nCost^2(i,j)\=sum_{i=1}^nsum_{j=1}^n(R_i+C_j-B_{ij})^2\=sum_{i=1}^n[(R_i+C_1-B_{i1})^2+dots(R_i+C_n-B_{in})^2]\=sum_{i=1}^n[(R_i+C_1)^2+B_{i1}-2B_{i1}(R_i+C_1)+dots]\=sum_{i=1}^n[(nR_i^2+(C_1^2+dots C_n^2)+2R_iA)+R_i-2R_i^2-sum_{j=1}^n2B_{ij}C_j]
Sum=i=1∑nj=1∑nCost2(i,j)=i=1∑nj=1∑n(Ri+Cj−Bij)2=i=1∑n[(Ri+C1−Bi1)2+…(Ri+Cn−Bin)2]=i=1∑n[(Ri+C1)2+Bi1−2Bi1(Ri+C1)+…]=i=1∑n[(nRi2+(C12+…Cn2)+2RiA)+Ri−2Ri2−j=1∑n2BijCj]
=
(
n
−
2
)
∑
i
=
1
n
R
i
2
+
n
∑
j
=
1
n
C
j
2
+
2
A
2
+
A
−
2
∑
i
=
1
n
∑
j
=
1
n
B
i
j
C
j
=
(
n
−
2
)
∑
i
=
1
n
R
i
2
+
(
n
−
2
)
∑
j
=
1
n
C
j
2
+
2
A
2
+
A
=(n-2)sum_{i=1}^nR_i^2+nsum_{j=1}^nC_j^2+2A^2+A-2sum_{i=1}^nsum_{j=1}^nB_{ij}C_j\=(n-2)sum_{i=1}^nR_i^2+(n-2)sum_{j=1}^nC_j^2+2A^2+A
=(n−2)i=1∑nRi2+nj=1∑nCj2+2A2+A−2i=1∑nj=1∑nBijCj=(n−2)i=1∑nRi2+(n−2)j=1∑nCj2+2A2+A
所以每次修改的时候找到原来的 R , C , A R,C,A R,C,A,再算出现在的比较计算就是答案。判断为1或0可以用set,注意每次操作后需要维护set。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+5;
const LL mod=1e9+7;
LL a[N],b[N];
struct node{
int x,y;
}e[N];
set<int>S[N];
int main(){
LL n,k,q;
scanf("%lld%lld%lld",&n,&k,&q);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=k;i++){
int x,y;scanf("%d%d",&x,&y);
e[i].x=x,e[i].y=y;
S[x].insert(y);
a[y]++,b[x]++;
}
for(int i=1;i<=n;i++)a[i]=n-a[i],b[i]=n-b[i];//num of 0
LL A=(n*n-k)%mod;
LL All=(2*A*A+A)%mod;
for(int i=1;i<=n;i++)All=(All+(n-2)*a[i]*a[i]%mod+(n-2)*b[i]*b[i]%mod)%mod;
printf("%lldn",All);
while(q--){
int x,y;
scanf("%d%d",&x,&y);
LL pre=((n-2)*a[y]*a[y]%mod+(n-2)*b[x]*b[x]%mod+2*A*A%mod+A)%mod;
LL now;
if(S[x].find(y)==S[x].end()){//0->1
now=((n-2)*(a[y]-1)%mod*(a[y]-1)%mod+(n-2)*(b[x]-1)%mod*(b[x]-1)%mod+2*(A-1)*(A-1)%mod+A-1)%mod;
A--,a[y]--,b[x]--;
S[x].insert(y);
}
else{
now=((n-2)*(a[y]+1)%mod*(a[y]+1)%mod+(n-2)*(b[x]+1)%mod*(b[x]+1)%mod+2*(A+1)*(A+1)%mod+A+1)%mod;
A++,a[y]++,b[x]++;
S[x].erase(y);
}
All=((All+now-pre)%mod+mod)%mod;
printf("%lldn",All);
}
}
最后
以上就是欢呼龙猫最近收集整理的关于ECNU 2018.10 月赛 C(数学统计)的全部内容,更多相关ECNU内容请搜索靠谱客的其他文章。
发表评论 取消回复