B . 渐进式广场 B.渐进式广场 B.渐进式广场 每次测试时限: 2 秒 每次测试时限:2 秒 每次测试时限:2秒 每次测试的内存限制: 256 兆字节 每次测试的内存限制:256 兆字节 每次测试的内存限制:256兆字节
题目描述
大小为 n n n 的累进正方形是一个 n × n n \times n n×n 矩阵。马克西姆选择三个整数 a 1 , 1 a_{1,1} a1,1 、 c c c 和 d d d ,并根据以下规则构造一个累进正方形:
a i + 1 , j = a i , j + c a_{i+1,j} = a_{i,j} + c ai+1,j=ai,j+c
a i , j + 1 = a i , j + d a_{i,j+1} = a_{i,j} + d ai,j+1=ai,j+d
例如,如果 n = 3 n = 3 n=3 、 a 1 , 1 = 1 a_{1,1} = 1 a1,1=1 、 c = 2 c=2 c=2 和 d = 3 d=3 d=3 ,那么递进方格如下:
( 1 4 7 3 6 9 5 8 11 ) \begin{pmatrix} 1 & 4 & 7 \\ 3 & 6 & 9 \\ 5 & 8 & 11 \end{pmatrix} 1354687911
上个月,马克西姆构建了一个递阶方阵,并记住了 n n n 、 c c c 和 d d d 的值。最近,他发现了一个由 n 2 n^2 n2 个整数随机排列而成的数组 b b b ,并想确定这些元素就是那个特定正方形的元素。
可以证明,对于 n n n 、 a 1 , 1 a_{1,1} a1,1 、 c c c 和 d d d 中的任意值,恰好存在一个满足所有规则的递进正方形。
输入
第一行包含一个整数 t t t ( 1 ≤ t ≤ 10 4 1 \le t \le {10} ^ 4 1≤t≤104 ) - 测试用例的数量。
每个测试用例的第一行包含三个整数 n n n 、 c c c 和 d d d ( 2 ≤ n ≤ 500 2 \le n \le 500 2≤n≤500 , 1 ≤ c , d ≤ 1 0 6 1 \le c, d \le 10^6 1≤c,d≤106 )–正方形的大小以及语句中描述的 c c c 和 d d d 的值。
每个测试用例的第二行包含 n ⋅ n n \cdot n n⋅n 个整数 b 1 , b 2 , … , b n ⋅ n b_1, b_2, \dots, b_{n \cdot n} b1,b2,…,bn⋅n ( 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1≤bi≤109 ) - 马克西姆找到的元素。
保证所有测试用例中 n 2 n ^ 2 n2 的总和不超过 25 ⋅ 10 4 25 \cdot {10} ^ 4 25⋅104 。
输出
对于每个测试用例,如果可以用数组元素 a a a 构建出给定的 n n n 、 c c c 和 d d d 的渐进正方形,则另起一行输出 “是”,否则输出 “否”。
您可以以任何大小写(小写或大写)输出每个字母。例如,字符串 “yEs”、“yes”、"Yes "和 "YES "将被视为肯定答案。
思路:
我们可以发现当最小值确定时,它所对应的累进正方形里面的各个值也就跟着确定下来了。所以可以先找到给定数组中的最小值,然后利用该最小值去推出正确的累进正方形中的值因该是什么,然后与给定的数组中的元素去比较就可以了。
细节:
这道题目要注意一个很重要的细节——>不要使用unordered_map,要使用map
。
为什么呢?这是因为unordered_map是通过哈希表实现的,虽然平均时间复杂度为 O ( 1 ) O(1) O(1),但是不太稳定,当数据比较刁钻或者设计的哈希函数不合理的时候,会使得各个键值对的键带入哈希函数得到的哈希值始终相同,从而使得所有键值对始终存储在同一链表上,这样会导致时间复杂度降为 O ( n ) O(n) O(n)。
而map
是通过红黑树
实现的,虽然平均时间复杂度为 O ( l o g n ) O(logn) O(logn),但是非常的稳定。
下图中第二个是使用了
map
,第一个是使用了unordered_map
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
bool solve()
{
int Min=2e9;
map<int,int>mp; //注意这里必须要用map,不要使用unordered_map
int n,c,d; cin>>n>>c>>d;
for(int i=1;i<=n*n;i++)
{
int temp; cin>>temp;
mp[temp]++;
Min=min(Min,temp);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
if(mp[Min+(j-1)*d]==0)return false;
else mp[Min+(j-1)*d]--;
Min+=c;
}
return true;
}
int main()
{
int t; cin>>t;
while(t--)
{
if(solve())cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}