Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

นับตัวเลขในช่วงที่มี GCD ของกำลังของตัวประกอบเฉพาะเท่ากับ 1 ใน C++


กำหนดตัวเลขสองตัวเริ่มต้นและสิ้นสุดแทนช่วงของจำนวนเต็มบวก เป้าหมายคือการหาการนับของตัวเลขทั้งหมดที่อยู่ในช่วง [start,end] และแยกตัวประกอบเฉพาะเพื่อให้ตัวประกอบเฉพาะทั้งหมดของจำนวนนั้นมีกำลังจนมี GCD เป็น 1

หากตัวเลขมีการแยกตัวประกอบเฉพาะเป็น 2 p * 3 q * 5 ….. จากนั้นยกกำลัง p,q,r ...ควรมี gcd=1.

ให้เราเข้าใจด้วยตัวอย่าง

ตัวอย่าง

ป้อนข้อมูล - เริ่มต้น =1 สิ้นสุด =10

ผลลัพธ์ - การนับจำนวนในช่วงที่มี GCD ของกำลังของตัวประกอบเฉพาะเท่ากับ 1 คือ:6

คำอธิบาย - ตัวเลขคือ:

2 ( 2 1 ), 3 ( 3 1 ), 5 ( 5 1 ), 7 ( 7 1 ), 8 ( 2 3 ) และ 10 ( 2 1 *5 1 ). ยกกำลังทั้งหมดของการแยกตัวประกอบเฉพาะแต่ละตัวมี gcd เป็น 1

ป้อนข้อมูล - เริ่มต้น =11 สิ้นสุด =20

ผลลัพธ์ - การนับจำนวนในช่วงที่มี GCD ของกำลังของตัวประกอบเฉพาะเท่ากับ 1 คือ:9

คำอธิบาย - ตัวเลขคือ:

11 ( 11 1 ), 12 ( 3 1 *2 2 ), 13 ( 13 1 ), 14 ( 2 1 *7 1 ), 15 ( 3 1 *5 1 ), 17 ( 17 1 ), 18 ( 2 1 *3 2 ), 19 ( 19 1 ) และ 20 ( 2 2 *5 1 ). ยกกำลังทั้งหมดของการแยกตัวประกอบเฉพาะแต่ละตัวมี gcd เป็น 1

แนวทางที่ใช้ในโปรแกรมด้านล่างมีดังนี้

ในแนวทางนี้ เราจะนับตัวเลขทั้งหมดในช่วงเริ่มต้นจนจบซึ่งไม่ใช่กำลังสมบูรณ์ เนื่องจากพลังที่ไม่สมบูรณ์จะเป็นไปตามเงื่อนไขข้างต้น สำหรับสิ่งนี้ เราจะพบพลังที่สมบูรณ์แบบทั้งหมดและลบมันออกจากจำนวนทั้งหมด

คำตอบจะเป็น =start-end +1 - ( นับจำนวนในช่วง[start,end] ที่เป็นกำลังสมบูรณ์ )

  • นำตัวแปรช่วงเริ่มต้นและสิ้นสุดเป็นอินพุต
  • ใช้ vector vec เพื่อเก็บพลังที่มากกว่า 3
  • กำหนดเซตเพื่อเก็บตัวเลขที่เป็นกำลังสองสมบูรณ์
  • ตั้ง sett_2 เพื่อเก็บตัวเลขที่ไม่ใช่กำลังสองสมบูรณ์
  • Function คำนวณ() เติมเวกเตอร์ vec และตั้งค่า sett และ sett_2 ในการแยกตัวเลขที่เป็นกำลังสองสมบูรณ์ ไม่ใช่กำลังสองสมบูรณ์และยกกำลัง>3
  • ทราเวอร์โดยใช้ for loop จาก i=2 ถึง i
  • ใส่พลังที่สมบูรณ์แบบ i*i เพื่อเซ็ตตัว
  • IF sett.find(i) !=sett.end()) คืนค่า true แล้ว i เป็นกำลังสองสมบูรณ์และอยู่ใน sett ดังนั้นไม่ต้องทำอะไร
  • เรียกใช้ในขณะที่วนซ้ำจนกว่ากำลังของจำนวนปัจจุบันจะเหลือน้อยกว่ามาก
  • ใส่พาวเวอร์คี่ลงใน sett_2 เนื่องจากเลขคู่เป็นกำลังสองที่สมบูรณ์แบบและอยู่ในเซ็ต
  • ในตอนท้าย แทรกค่าที่จัดเรียงของ sett_2 ไปยัง vector vec โดยใช้ for loop
  • ฟังก์ชัน GCD_1(การเริ่มต้น int แบบยาว, int แบบยาว) ใช้ช่วงเป็นอินพุตและส่งกลับการนับตัวเลขในช่วงที่มี GCD ยกกำลังของปัจจัยเฉพาะเท่ากับ 1
  • โทรคำนวณ().
  • คำนวณกำลังสองที่สมบูรณ์แบบในช่วง per_sq =floor(sqrtl(end)) - floor(sqrtl(start - 1))
  • คำนวณค่าสูงสุดของการเริ่มต้นใน vec โดยใช้ upper_bound(vec.begin(), vec.end(), end) - vec.begin()
  • ค่าที่ต่ำกว่าของ end ใน vec ในทำนองเดียวกันโดยใช้ bottom =lower_bound(vec.begin(), vec.end(), start) - vec.begin()
  • คำนวณกำลังที่สมบูรณ์แบบตาม per_pow =per_sq + (บน - ล่าง)
  • คำตอบจะถูกนับ =(จบ - เริ่ม + 1) - per_pow.
  • ผลตอบแทนนับเป็นผลลัพธ์ในตอนท้าย

ตัวอย่าง

#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