题目内容
给定一个长度为 n n n 的数组 a a a ,问是否可以选择三个下标不同的元素 a i , a j , a k a_i,a_j,a_k ai,aj,ak ,满足 a i + a j + a k a_i+a_j+a_k ai+aj+ak 的个位数为 3 3 3 。
数据范围
- 3 ≤ n ≤ 2 ⋅ 1 0 5 3\leq n\leq 2\cdot 10^5 3≤n≤2⋅105
- 1 ≤ a i ≤ 1 0 9 1\leq a_i\leq 10^9 1≤ai≤109
题解
和的个位数为 3 3 3 只与每个数的个位有关,所以用一个长度为 10 10 10 的数组保存每个数的数量。
不妨假定三个数中
- a i a_i ai 的个位数小于等于 a j a_j aj 的个位数
- a j a_j aj 的个位数小于等于 a k a_k ak 的个位数
如果我们选择了两个或三个个位数相同的数,需要保证这个个位数对应数的数量足够,所以可以在选择之后将其数量减 1 ,继续枚举之后的数,在本轮枚举结束后,将其数量加 1 恢复回来。
时间复杂度: O ( 10 ∗ 10 ∗ 10 ) O(10*10*10) O(10∗10∗10)
代码
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n;
cin >> n;
vector<int> cnt(10);
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
cnt[a[i] % 10] += 1;
}
for (int i = 0; i < 10; ++i) {
if (!cnt[i]) continue;
cnt[i] -= 1;
for (int j = i; j < 10; ++j) {
if (!cnt[j]) continue;
cnt[j] -= 1;
for (int k = j; k < 10; ++k) {
if (!cnt[k]) continue;
cnt[k] -= 1;
if ((i + j + k) % 10 == 3) {
cout << "YES\n";
return;
}
cnt[k] += 1;
}
cnt[j] += 1;
}
cnt[i] += 1;
}
cout << "NO\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}