Skip to content

C15: Mẹo thi đấu C++ — Template, Macro, Trick

Bạn sẽ học được: Template thi đấu, macro, shortcut, trick hay
Yêu cầu: Đã học C14 (Algorithm nâng cao)
Thời gian: 30 phút


Template thi đấu — Copy-paste là xong

Template cơ bản

1
2
3
4
5
6
7
8
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    return 0;
}

Template đầy đủ

#include <bits/stdc++.h>
using namespace std;

// Định nghĩa kiểu dữ liệu
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

// Hằng số
const int MOD = 1e9 + 7;
const int INF = 1e9;
const long long LLINF = 1e18;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    return 0;
}

Lưu template vào file

Tạo file template.cpp trong thư mục thi đấu. Mỗi lần bắt đầu bài mới, chỉ cần copy-paste.


Macro — Viết ngắn hơn

Các macro thường dùng

// Rút gọn kiểu dữ liệu
#define ll long long
#define pii pair<int, int>
#define vi vector<int>
#define vll vector<long long>

// Rút gọn hàm
#define pb push_back
#define mp make_pair
#define fi first
#define se second

// Rút gọn vòng lặp
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define FORD(i, a, b) for (int i = (a); i >= (b); i--)
#define REP(i, n) FOR(i, 0, (n) - 1)

// Debug
#define dbg(x) cerr << #x << " = " << x << endl

Sử dụng macro

1
2
3
4
5
6
7
8
9
// Thay vì viết:
vector<pair<int, int>> v;
v.push_back(make_pair(1, 2));
cout << v[0].first << endl;

// Viết ngắn hơn:
vi v;
v.pb(mp(1, 2));
cout << v[0].fi << endl;

Cẩn thận với macro

  • Macro chỉ là thay thế text, không phải hàm
  • Có thể gây lỗi không ngờ
  • Chỉ dùng trong thi đấu, không dùng trong code production

Trick hay trong thi đấu

Trick 1: Đọc n số nguyên nhanh

// Cách thường
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];

// Cách ngắn hơn
int n;
cin >> n;
vector<int> a(n);
for (auto &x : a) cin >> x;

Trick 2: In mảng nhanh

1
2
3
4
5
// Cách thường
for (int i = 0; i < n; i++) cout << a[i] << " ";

// Cách ngắn hơn
for (int x : a) cout << x << " ";

Trick 3: Tính tổng nhanh

1
2
3
4
5
6
// Cách thường
long long sum = 0;
for (int x : a) sum += x;

// Cách ngắn hơn
long long sum = accumulate(a.begin(), a.end(), 0LL);

Trick 4: Tìm min/max nhanh

1
2
3
4
5
6
// Cách thường
int minVal = a[0];
for (int x : a) minVal = min(minVal, x);

// Cách ngắn hơn
int minVal = *min_element(a.begin(), a.end());

Trick 5: Đảo ngược mảng

reverse(a.begin(), a.end());

Trick 6: Sắp xếp giảm dần

sort(a.begin(), a.end(), greater<int>());

Trick 7: Kiểm tra số nguyên tố nhanh

1
2
3
4
5
6
7
bool isPrime(int n) {
    if (n < 2) return false;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) return false;
    }
    return true;
}

Trick 8: Tính GCD nhanh

// Dùng hàm có sẵn (C++17: std::gcd trong <numeric>)
int g = gcd(a, b);  // cần #include <numeric> và using namespace std;

// Hoặc dùng __gcd (GCC extension, không chuẩn C++)
// int g = __gcd(a, b);

// Hoặc tự viết
int gcd(int a, int b) {
    while (b) { int r = a % b; a = b; b = r; }
    return a;
}

Xử lý lỗi thường gặp

Lỗi 1: Tràn số

1
2
3
4
5
6
7
// ❌ SAI
int sum = 0;
for (int i = 0; i < n; i++) sum += a[i];

// ✅ ĐÚNG
long long sum = 0;
for (int i = 0; i < n; i++) sum += a[i];

Lỗi 2: Quên modulo

1
2
3
4
5
// ❌ SAI
int result = (a * b) % MOD;

// ✅ ĐÚNG (tránh tràn)
long long result = (1LL * a * b) % MOD;

Lỗi 3: Nhầm ===

1
2
3
4
5
// ❌ SAI
if (x = 5) { ... }

// ✅ ĐÚNG
if (x == 5) { ... }

Cheat sheet — Bảng tra cứu nhanh

Nhập/xuất

1
2
3
4
5
6
7
// Nhập
cin >> a >> b;
getline(cin, s);

// Xuất
cout << a << " " << b << endl;
printf("%d %d\n", a, b);

Vector

1
2
3
4
5
6
vector<int> a(n);
a.push_back(x);
a.pop_back();
a.size();
sort(a.begin(), a.end());
reverse(a.begin(), a.end());

String

1
2
3
4
5
string s;
s.length();
s.substr(pos, len);
s.find(sub);
getline(cin, s);

Set/Map

1
2
3
4
5
6
7
8
set<int> s;
s.insert(x);
s.count(x);
s.erase(x);

map<string, int> m;
m[key] = value;
m.count(key);

Algorithm

1
2
3
4
5
6
7
sort(a.begin(), a.end());
reverse(a.begin(), a.end());
unique(a.begin(), a.end());
lower_bound(a.begin(), a.end(), x);
upper_bound(a.begin(), a.end(), x);
binary_search(a.begin(), a.end(), x);
next_permutation(a.begin(), a.end());

Bài tập thực hành

Bài 1: Template

Tạo file template.cpp với template thi đấu đầy đủ. Dùng template để đọc \(n\) số nguyên và in tổng.

Lời giải
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define REP(i, n) for (int i = 0; i < (n); i++)

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    ll sum = 0;
    int x;
    REP(i, n) {
        cin >> x;
        sum += x;
    }
    cout << sum << endl;
    return 0;
}

Bài 2: Viết ngắn gọn

Viết lại đoạn code sau bằng macro:

1
2
3
4
5
6
vector<pair<int, int>> v;
v.push_back(make_pair(1, 2));
v.push_back(make_pair(3, 4));
for (int i = 0; i < v.size(); i++) {
    cout << v[i].first << " " << v[i].second << endl;
}
Lời giải
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>

int main() {
    vector<pii> v;
    v.pb({1, 2});
    v.pb({3, 4});
    for (auto &[x, y] : v) {
        cout << x << " " << y << endl;
    }
    return 0;
}

Tóm tắt bài học

Nội dung Chi tiết
Template #include <bits/stdc++.h> + ios_base::sync_with_stdio(false)
Macro #define ll long long, #define pb push_back
Trick for (auto &x : a) cin >> x;
Cheat sheet Bảng tra cứu nhanh

Bài viết liên quan


Bài tiếp theo: C16: Bài tập tổng hợp →


💬 Bình luận