กำหนดสองตัวเลข start และ end แทนช่วงของจำนวนเต็มบวก เป้าหมายคือหาจำนวนตัวเลขทั้งหมดที่อยู่ในช่วง [start, end] และมีการแยกตัวประกอบเฉพาะอย่างที่กำลังของเฉพาะตัวประกอบทั้งหมดมี GCD เท่ากับ 1
ถ้าตัวเลขมีการแยกตัวประกอบเฉพาะเป็น 2p * 3q * 5r ... แล้วกำลัง p, q, r ... ควรจะมี gcd = 1
ทำความเข้าใจด้วยตัวอย่าง
ตัวอย่าง
Input - start = 1, end = 10
Output - จำนวนตัวเลขในช่วงที่ GCD ของกำลังของเฉพาะตัวประกอบเท่ากับ 1 คือ: 6
คำอธิบาย - ตัวเลขคือ:
2 (21), 3 (31), 5 (51), 7 (71), 8 (23) และ 10 (21*51) กำลังของเฉพาะตัวประกอบแต่ละตัวมี gcd เท่ากับ 1
Input - start = 11, end = 20
Output - จำนวนตัวเลขในช่วงที่ GCD ของกำลังของเฉพาะตัวประกอบเท่ากับ 1 คือ: 9
คำอธิบาย - ตัวเลขคือ:
11 (111), 12 (31*22), 13 (131), 14 (21*71), 15 (31*51), 17 (171), 18 (21*32), 19 (191) และ 20 (22*51) กำลังของเฉพาะตัวประกอบแต่ละตัวมี gcd เท่ากับ 1
แนวทางที่ใช้ในโปรแกรมด้านล่าง
ในแนวทางนี้ เราจะนับตัวเลขทั้งหมดในช่วง start ถึง end ที่ไม่ใช่ perfect power เนื่องจาก non-perfect powers จะทำให้เงื่อนไขข้างต้นเป็นจริง สำหรับนี้ เราจะหา perfect powers ทั้งหมดและลบออกจากจำนวนรวม
คำตอบ = start - end + 1 - (จำนวนตัวเลขในช่วง [start, end] ที่เป็น perfect powers)
- รับตัวแปรช่วง start และ end เป็นอินพุต
- รับ vector vec เก็บกำลังที่มากกว่า 3
- รับ set sett เก็บตัวเลขที่เป็น perfect squares
- รับ set sett_2 เก็บตัวเลขที่ไม่ใช่ perfect squares
- ฟังก์ชัน calculate() เติม vector vec และ set sett, sett_2 เพื่อแยกตัวเลขที่เป็น perfect squares, non-perfect squares และกำลัง > 3
- วนลูป for จาก i = 2 ถึง i < size
- เพิ่ม perfect powers i*i เข้า sett
- IF sett.find(i) != sett.end() คืนค่า true แล้ว i เป็น perfect square อยู่ใน sett แล้ว ข้ามไป
- รัน while loop จนกว่ากำลังของตัวเลขปัจจุบันจะน้อยกว่า large
- เพิ่มกำลังคี่เข้า sett_2 เพราะกำลังคู่เป็น perfect squares อยู่ใน sett แล้ว
- ในที่สุด ใส่ค่าที่เรียงแล้วของ sett_2 เข้า vector vec ด้วย for loop
- ฟังก์ชัน GCD_1(long int start, long int end) รับช่วงเป็นอินพุตและคืนค่าจำนวนตัวเลขในช่วงที่ GCD ของกำลังของเฉพาะตัวประกอบเท่ากับ 1
- เรียก calculate()
- คำนวณ perfect squares ในช่วง per_sq = floor(sqrtl(end)) - floor(sqrtl(start - 1))
- คำนวณค่าบนของ start ใน vec ด้วย upper_bound(vec.begin(), vec.end(), end) - vec.begin()
- คำนวณค่าล่างของ end ใน vec ด้วย lower_bound(vec.begin(), vec.end(), start) - vec.begin()
- คำนวณ perfect powers per_pow = per_sq + (top - bottom)
- คำตอบคือ count = (end - start + 1) - per_pow
- คืนค่า count เป็นผลลัพธ์ในที่สุด
ตัวอย่าง
#include <bits/stdc++.h>
using namespace std;
#define size 1000005
#define large 1e18
vector < long int > vec;
set < long int > sett;
set < long int > sett_2;
void calculate() {
for (long int i = 2; i < size; i++) {
sett.insert(i * i);
if (sett.find(i) != sett.end()) {
continue;
}
long int total = i;
while (i * i <= large / total) {
total *= (i * i);
sett_2.insert(total);
}
}
for (auto it: sett_2) {
vec.push_back(it);
}
}
long int GCD_1(long int start, long int end) {
calculate();
long int per_sq = floor(sqrtl(end)) - floor(sqrtl(start - 1));
long int top = upper_bound(vec.begin(), vec.end(), end) - vec.begin();
long int bottom = lower_bound(vec.begin(), vec.end(), start) - vec.begin();
long int per_pow = per_sq + (top - bottom);
long int count = (end - start + 1) - per_pow;
return count;
}
int main() {
long int start = 10, end = 40;
cout << "Count of numbers in a range having GCD of powers of prime factors equal to 1 are: " << GCD_1(start, end);
return 0;
}
หากเรารันโค้ดข้างต้น จะได้ผลลัพธ์ดังนี้
ผลลัพธ์
Count of numbers in a range having GCD of powers of prime factors equal to 1 are: 7