Kiểm tra đầu vào
Bài
# |
Bài |
Điểm |
1 |
Lặp lại
|
100 |
2 |
Ốc sên
|
100 |
3 |
Đếm số
|
100 |
4 |
Tìm giá trị nhỏ nhì
|
100 |
5 |
Tìm số Fibonacci
|
100 |
6 |
Mua sách
|
100 |
7 |
Đếm cặp số nguyên tố cùng nhau
|
100 |
8 |
Tổng k số
|
100 |
9 |
Bài dễ
|
100 |
10 |
Two pointer 1A
|
100 |
Tất cả bài tập
Thời gian |
Bài |
Mô tả |
Tháng 2 23, 2025, 8:14 |
Bài dễ
|
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
// Đọc mảng a (sử dụng mảng 1-indexed)
vector<long long> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
// Tính tổng lũy tích: P[0] = 0, P[i] = a_1 + a_2 + ... + a_i
vector<long long> prefix(n + 1, 0);
for (int i = 1; i <= n; i++)
{
prefix[i] = prefix[i - 1] + a[i];
}
// Tạo sieve để xác định số nguyên tố từ 1 đến n
vector<bool> isPrime(n + 1, true);
isPrime[0] = isPrime[1] = false; // 0 và 1 không phải số nguyên tố
for (int i = 2; i * i <= n; i++)
{
if (isPrime[i])
{
for (int j = i * i; j <= n; j += i)
{
isPrime[j] = false;
}
}
}
// Biến lưu kết quả: tổng lớn nhất của đoạn đẹp
long long ans = -1e18; // Khởi tạo với một giá trị rất nhỏ
long long minPrefix; // Lưu giá trị nhỏ nhất của prefix[L-1] từ các L là số nguyên tố
bool first = true; // Cờ đánh dấu xử lý số nguyên tố đầu tiên
// Duyệt các chỉ số từ 2 đến n (vì 1 không phải số nguyên tố)
for (int i = 2; i <= n; i++)
{
if (isPrime[i])
{ // Nếu i là số nguyên tố, có thể dùng làm R
if (first)
{
// Với số nguyên tố đầu tiên, đoạn [i,i] có tổng = a[i] = prefix[i] - prefix[i-1]
ans = prefix[i] - prefix[i - 1];
minPrefix = prefix[i - 1]; // Khởi tạo minPrefix cho các đoạn sau
first = false;
}
else
{
// Cập nhật tổng lớn nhất: sử dụng minPrefix đã gặp từ các L (với L là số nguyên tố)
ans = max(ans, prefix[i] - minPrefix);
// Cập nhật minPrefix với prefix[i-1] nếu nhỏ hơn
minPrefix = min(minPrefix, prefix[i - 1]);
}
}
}
cout << ans << endl;
return 0;
}
|