2^x * 3^y formasında olan ədədlərin sayı#9021

2^x * 3^y formasında olan ədədlərin sayı (Həll təhlili)

2^x * 3^y şəklində olan və 10^{18}-dən çox olmayan rəqəmlər o qədər də çox deyil. Onları yaradaraq massivində saxlayacağıq.

Müəyyən bir intervalda olan f(a, b) şəklində olan rəqəmlərin sayını aşağıdakı formada tapa bilərik:

f(0, b) - f(0, a - 1)

Burada f(0, q) -dən böyük olmayan 2^x * 3^y şəklində olan rəqəmlərin sayını ifadə edir. Bu sorğunun cavabını massivində ikili axtarış yolu ilə tapa bilərik.

Nümunə

-dən çox olmayan 2^x * 3^y şəklində olan bütün rəqəmləri yaradacağıq.

intervalına rəqəm aiddir (mavi rənglə qeyd olunub).

intervalına rəqəm aiddir (yaşıl rənglə qeyd olunub).

intervalı üçün həllini tapaq:

upper\_bound(v.begin(), v.end(), 20) - upper\_bound(v.begin(), v.end(), 9) = 3

Doğrudan da, intervalına axtarılan rəqəm aiddir:

12, 16, 18

Alqoritmin reallaşdırılması

MAX = 10^{18} sabitini və iş massivini elan edəcəyik.

#define MAX 1000000000000000000LL
vector<long long> v;

preprocess funksiyası 10^{18}-dən çox olmayan bütün 2^x * 3^y şəklində olan rəqəmləri yaradır və onları massivində saxlayır. Hər bir x = 1, 2, 4, 8, ... üçün y = 1, 3, 9, 27, ... rəqəmlərini nəzərdən keçiririk, ta ki x * y < MAX olana qədər.

void preprocess()
{
  long long x = 1, y = 1;
  while (x < MAX)
  {
    while (x * y < MAX)
    {
      v.push_back(x * y);
      y *= 3;
    }
    x *= 2;
    y = 1;
  }

Sayıları massivində sıralağın.

  sort(v.begin(), v.end());
}

Proqramın əsas hissəsi. 2^x * 3^y rəqəmləri massivini yaradırıq.

preprocess();

Sorğunu oxuyuruq — intervalı. Bu intervalda axtarılan rəqəmlərin sayı aşağıdakı formada hesablanır:

f(a, b) = f(0, b) - f(0, a - 1)
while (scanf("%lld %lld", &a, &b) == 2)
{
  res = upper_bound(v.begin(), v.end(), b) – upper_bound(v.begin(), v.end(), a - 1);
  printf("%lld\n", res);
}