题解:P11001 [蓝桥杯 2024 省 Python B] 连连看

· · 题解

题目大意

给定一个矩阵,求其中每一条斜线中数字相同的数对的个数(每一对重复算两次)。

解法

这个数据大小显然不能直接暴力枚举( O(n^{2}m) 左右的复杂度),这里可以通过空间节省时间。

预处理

首先在输入时进行预处理,使用桶并把它处理成斜线格式。

x\y 1 2
1 1 2
2 2 3
3 3 2

具体方法(以样例为例):

先看每一条斜向上的线,不难发现其横坐标 j 和纵坐标 i 之和相等(如 3+1=2+2=2 )。
所以有 u[i+j][x]++; ( x 即为 A_{i,j} )。

同理,斜向下的线则有 i 与 j 之差相等的共同点。
不过由于 i 与 j 的大小不确定,所以这里下标都加上一千( A_{i,j} 的最大值)以防止数组越界,所以有 d[1000+i-j][x]++; 。

计算答案

对于每一条斜线上,若有 x 个相同的数,则有 x(x-1) 个符合要求的数对。

原因:

$x=3$ 时,有一和二,一和三,二和三三种,重复则有六对。 依次类推,当 $x=k$ 时,共有 $k(k-1)/2$ 种(高斯求和),所以有 $k(k-1)$ 对。 用变量 $ans$ 累加答案即可。 ## AC code: ```cpp #include<bits/stdc++.h> using namespace std; int n,m,u[2001][2001],d[2001][2001],x,ans; signed main() { cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&x); u[i+j][x]++; d[1000+i-j][x]++; } } for(int i=1;i<=2000;i++) { for(int j=1;j<=2000;j++) { ans+=(-1+u[i][j])*u[i][j]; ans+=(-1+d[i][j])*d[i][j]; } } } cout<<ans; return 0; } ```