※ 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 34316번 문제인 사각형 개수 세기이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/34316
\(NM\le10^5\) 제약조건을 눈여겨보자. 이 조건으로부터 \(\min(N,M)\le\sqrt{10^5}\)임을 알 수 있다. 이러한 형태로 문제에서 주어지는 입력에 추가적인 제한을 주는 경우는 제법 자주 나타나므로 잘 알아두는 것이 좋다.
\(N\)과 \(M\) 중 더 작은 값을 행의 개수로 하고, 두 개의 행을 골라 각 열의 두 행의 수의 합을 각각 구하는 작업의 시간복잡도는 \(O(\min(N,M)^2\max(N,M))=O(\min(N,M)NM)\)과 같다. \(NM\le10^5\)와 \(\min(N,M)\le\sqrt{10^5}\)가 성립하므로, 이와 같은 접근의 연산량은 1초 안에 충분히 수행 가능하는 점을 관찰할 수 있다. 여기까지 관찰했다면 이후의 계산은 어렵지 않을 것이다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
int R, C;
vector<int> v[316];
ll ans;
int cnt[20];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> R >> C;
if (R < C) {
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) cin >> v[r].emplace_back();
}
}
else {
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) {
cin >> v[c].emplace_back();
}
}
swap(R, C);
}
for (int r1 = 0; r1 < R; r1++) {
for (int r2 = r1 + 1; r2 < R; r2++) {
memset(cnt, 0, sizeof(cnt));
for (int c = 0; c < C; c++) {
cnt[v[r1][c] + v[r2][c]]++;
}
for (int i = 2; i < 10; i++) ans += cnt[i] * cnt[20 - i];
int v1 = cnt[10], v2 = v1 - 1;
if (v1 & 1) v2 /= 2;
else v1 /= 2;
ans += v1 * v2;
}
}
cout << ans;
}728x90
'BOJ' 카테고리의 다른 글
| [BOJ 8551 // C++] Blokada (0) | 2026.02.24 |
|---|---|
| [BOJ 33922 // C++] 책 쌓기 (0) | 2026.02.10 |
| [BOJ 33921 // C++] 아름다운 수열 (0) | 2026.02.09 |
| [BOJ 22516 // C++] Magical Girl Sayaka-chan (0) | 2026.01.30 |
| [BOJ 27470 // C++] 멋진 부분집합 (0) | 2025.12.01 |