bài tập

You might also like

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 3

#include <stdio.

h>
#define LLONG_MAX 9223372036854775807LL
#define LLONG_MIN (-LLONG_MAX - 1)

int main(){
int n, m;
scanf("%d %d", &n, &m);
long long a[n + 1];
long long sum = 0;
long long Max = LLONG_MIN;
for(int i = 1; i <= n; ++i){
scanf("%lld", &a[i]);
sum += a[i];
if(a[i] > Max) Max = a[i];
}

if(m == 1){
printf("%lld", sum);
return 0;
}
if(m == n){
printf("%lld", Max);
return 0;
}

long long left = Max, right = sum;


while(left <= right){
long long mid = (left + right) / 2;
int k = 1;
long long s = 0;
for(int i = 1; i <= n; ++i){
if(s + a[i] <= mid){
s += a[i];
}
else{
s = a[i];
k++;
}
}

if(k <= m){


right = mid - 1;
}
else{
left = mid + 1;
}
}
printf("%lld", left);
return 0;
}

Đoạn code này là một chương trình C để giải bài toán "Phân chia dãy số" trong kỳ
thi NOI Online 2021. Bài toán yêu cầu chia một dãy số thành một số lượng mảnh sao
cho tổng của giá trị lớn nhất trong các mảnh này là nhỏ nhất có thể.

Dòng đầu tiên #include <stdio.h> khai báo thư viện tiêu chuẩn của C để sử dụng hàm
nhập/xuất từ bàn phím và ra màn hình.
Dòng thứ hai và thứ ba định nghĩa hai hằng số LLONG_MAX và LLONG_MIN, lần lượt là
giá trị lớn nhất và giá trị nhỏ nhất của kiểu dữ liệu long long. Kiểu long long
được sử dụng để lưu trữ các giá trị lớn hơn kiểu int.

Hàm main() là hàm chính của chương trình. Ta khởi tạo biến n và m để lưu trữ độ dài
của dãy số và số lượng mảnh cần chia. Hàm scanf("%d %d", &n, &m); sẽ đọc hai giá
trị này từ bàn phím.

Tiếp theo, ta khai báo một mảng a có độ dài n+1 để lưu trữ dãy số và khởi tạo giá
trị sum bằng 0 và Max bằng LLONG_MIN. Trong vòng lặp từ 1 đến n, ta đọc giá trị của
phần tử thứ i vào mảng a, tính tổng sum và cập nhật giá trị lớn nhất Max.

Ở hai điều kiện if(m == 1) và if(m == n) tiếp theo, ta xử lý những trường hợp đặc
biệt khi số lượng mảnh cần chia là 1 hoặc bằng độ dài của dãy số. Nếu m bằng 1, ta
in ra giá trị của sum và kết thúc chương trình. Nếu m bằng n, ta in ra giá trị Max
và kết thúc chương trình.

Trong trường hợp chung, ta sử dụng thuật toán tìm kiếm nhị phân để tìm giá trị nhỏ
nhất của tổng các mảnh sao cho số lượng mảnh không vượt quá m. Ban đầu, ta khởi tạo
giá trị left bằng Max và right bằng sum.

Vòng lặp while(left <= right) sẽ tiếp tục cho đến khi left lớn hơn right. Trong mỗi
vòng lặp, ta tính giá trị mid là trung bình của left và right. Sau đó, ta tính tổng
của các mảnh dãy số sao cho tổng này không vượt quá giá trị mid. Nếu số lượng mảnh
này không vượt quá m, ta cập nhật giá trị right bằng mid - 1. Ngược lại, ta cập
nhật giá trị left bằng mid + 1.

Cuối cùng, ta in ra giá tr

#include <stdio.h>

int main()
{
int n;
int k;
printf("Nhap so phan tu cua day: ");
scanf("%d", &n);
int a[n];
printf("Nhap so doan muon chia: ");
scanf("%d",&k);
int max;
int tong = 0;
for(int i = 0; i < n; i++)
{
printf("a[%d] = ",i);
scanf("%d", &a[i]);
tong = tong + a[i];
if(a[i] > max) max = a[i];
}

if(k == 1)
{
printf("%d", tong);
}
if(k == n)
{
printf("%d", max);
}
int l = max; int r = tong;
while(l <= r)
{
int mid = (l + r) / 2;
int dem = 1;
int sum = 0;
for(int i = 0; i < n; i++)
{
if(sum + a[i] <= mid)
{
sum = sum + a[i];
}
else
{
sum = a[i];
dem = dem + 1;
}
}

if(dem <= k)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
printf("Ket qua = %d", l);
return 0;
}

You might also like