โจทย์: หาจำนวนศูนย์ท้าย (trailing zeros) สูงสุดในผลคูณของเซตย่อย (subsets) ขนาด K จากอาร์เรย์ขนาด N
ตัวอย่าง
Input: Arr[] = {5, 20, 2}, K = 2
Output: 2
คำอธิบาย: เซตย่อยขนาด 2 มี 3 ชุด: - [5, 20] → 100 (2 ศูนย์ท้าย) - [20, 2] → 40 (1 ศูนย์ท้าย) - [5, 2] → 10 (1 ศูนย์ท้าย) ค่าสูงสุดคือ 2
Input: Arr[] = {60, 40, 25}, K = 2
Output: 3
แนวทางแก้ปัญหา (Dynamic Programming)
จำนวนศูนย์ท้ายขึ้นอยู่กับจำนวนคู่ของปัจจัย 2 และ 5 (เพราะ 10 = 2 × 5) ใช้ DP เก็บจำนวนปัจจัย 2 สูงสุดสำหรับแต่ละจำนวนปัจจัย 5
- กำหนด
M5 = 100(ขีดจำกัดปัจจัย 5) - สร้างตาราง
Sub[K+1][M5+5]เริ่มต้น -1,Sub[0][0] = 0 - แยกตัวประกอบแต่ละจำนวนในอาร์เรย์ หาจำนวน 2 (P2) และ 5 (P5)
- อัปเดตตาราง DP แบบ bottom-up
- คำตอบ = max(min(i, Sub[K][i])) สำหรับทุก i
โค้ดตัวอย่าง
#include <bits/stdc++.h>
using namespace std;
#define M5 100
int MaxZeros(int* Arr, int N, int K) {
int Sub[K+1][M5+5];
memset(Sub, -1, sizeof(Sub));
Sub[0][0] = 0;
for (int P = 0; P < N; P++) {
int P2 = 0, P5 = 0;
while (Arr[P] % 2 == 0) { P2++; Arr[P] /= 2; }
while (Arr[P] % 5 == 0) { P5++; Arr[P] /= 5; }
for (int i = K - 1; i >= 0; i--)
for (int j = 0; j < M5; j++)
if (Sub[i][j] != -1)
Sub[i + 1][j + P5] = max(Sub[i + 1][j + P5], Sub[i][j] + P2);
}
int ans = 0;
for (int i = 0; i < M5; i++)
ans = max(ans, min(i, Sub[K][i]));
return ans;
}
int main() {
int Arr[] = { 60, 40, 25 };
int K = 2;
int N = sizeof(Arr) / sizeof(Arr[0]);
cout << MaxZeros(Arr, N, K);
return 0;
}
ผลลัพธ์
3