Clasa a XII-a · Matematică pentru programareRead in English
Numărul multiplilor lui k dintr-un interval în C++
În engleză: Number of multiples of k in a range
Ideea
Câte numere din [a, b] se divid cu k? Numerele din [1, x] divizibile cu k sunt k, 2k, ..., (x / k) * k, adică x / k bucăți (împărțire întreagă). Scădem multiplii din [1, a - 1] și obținem b / k - (a - 1) / k, fără nicio buclă. Pentru „divizibile cu k1 sau cu k2” aplicăm includerea și excluderea: adunăm numărătorile pentru k1 și k2 și scădem pe cea pentru cmmmc(k1, k2). Programul afișează ambele rezultate. Se presupune 1 ≤ a ≤ b.
Descrierea în engleză
How many numbers in [a, b] are divisible by k? The numbers in [1, x] divisible by k are k, 2k, ..., (x / k) * k, i.e. x / k of them (integer division). We subtract the multiples in [1, a - 1] and get b / k - (a - 1) / k, without any loop. For 'divisible by k1 or by k2' we apply inclusion-exclusion: we add the counts for k1 and k2 and subtract the count for lcm(k1, k2). The program prints both results. We assume 1 ≤ a ≤ b.
- Complexitate
- O(log min(k1, k2)), de la calculul cmmdc
- Clasa
- Clasa a XII-a (Grade 12)
- Capitol
- Matematică pentru programare
Exemple
Intrare
10 100 3 5
Ieșire așteptată
30 43
Intrare
1 1000000000000 4 6
Ieșire așteptată
250000000000 333333333333
Codul C++
Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.
/*
* Titlu: Numărul multiplilor lui k dintr-un interval
* Clasa: 12
* Capitol: Matematică pentru programare
* Descriere: Câte numere din [a, b] se divid cu k? Numerele din [1, x] divizibile
* cu k sunt k, 2k, ..., (x / k) * k, adică x / k bucăți (împărțire
* întreagă). Scădem multiplii din [1, a - 1] și obținem
* b / k - (a - 1) / k, fără nicio buclă. Pentru „divizibile cu k1 sau
* cu k2” aplicăm includerea și excluderea: adunăm numărătorile pentru
* k1 și k2 și scădem pe cea pentru cmmmc(k1, k2). Programul afișează
* ambele rezultate. Se presupune 1 ≤ a ≤ b.
* Complexitate: O(log min(k1, k2)), de la calculul cmmdc
*
* Exemplu
* Intrare: 10 100 3 5
* Ieșire:
* 30
* 43
*
* Exemplu
* Intrare: 1 1000000000000 4 6
* Ieșire:
* 250000000000
* 333333333333
*/
#include <iostream>
using namespace std;
long long cmmdc(long long a, long long b)
{
while (b != 0)
{
long long r = a % b;
a = b;
b = r;
}
return a;
}
// Câți multipli de k sunt în intervalul [a, b].
long long multipli(long long a, long long b, long long k)
{
return b / k - (a - 1) / k;
}
int main()
{
long long a, b, k1, k2;
cin >> a >> b >> k1 >> k2;
long long cmmmc = k1 / cmmdc(k1, k2) * k2;
cout << multipli(a, b, k1) << '\n';
cout << multipli(a, b, k1) + multipli(a, b, k2) - multipli(a, b, cmmmc) << '\n';
return 0;
}
Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.