---
# System prepended metadata

title: k-factor solution

---

# Lời giải bài K-FACTOR

## Đề bài
Cho số nguyên dương $K$, số nguyên dương gọi là $N$ gọi là $K$-factor nếu $N$ có thể viết được bằng tích của các số nguyên dương bé hơn hay bằng $K$

Cho số $K$ và đoạn nguyên dương $[a,b]$, đếm xem trong đoạn $[a,b]$ có bao nhiêu số $K$-factor.
### Constraints
+ $2 \le K \le 10^5$
+ $1 \le a \le b \le 2 \cdot 10^9$
+ $b - a \le 2 \cdot 10^6$

## Ý tưởng

Cách tối ưu nhất để phân tích mỗi số là sử dụng thừa số nguyên tố. Giả sử ta có số $x$ như sau.
$$x = p_1^{e_1}\cdot p_2^{e_2} \cdot ... \cdot p_n^{e_n}$$
$$p_1 < p_2 < p_3 < ... < p_n$$
Số $x$ là $K$-factor khi $p_n < K$, không phải là $K$-factor khi $p_n > K$


Giả sử tồn tại vị trí $m (m \le n)$ sao cho
$$x = p_1^{e_1}\cdot p_2^{e_2} \cdot ... \cdot p_m^{e_m}\cdot ... \cdot p_n^{e_n}$$

$$p_m \le K$$

Vì $x \le 10^9$ và $b - a \le 2 \cdot 10^6$ nên ta không thể dùng sàng để phân tích thừa số nguyên tố được, hay phân tích thừa số nguyên tố trong $O(\sqrt{n})$ là quá chậm.

Dễ thấy rằng nếu $x$ là một số $K$-factor thì $\frac{x}{p_1^{e_1}\cdot p_2^{e_2} \cdot ... \cdot p_m^{e_m}} = 1$, nếu không thì giá trị $> 1$.

Với $K \le 10^5$, ta có thể dễ dàng tìm các số nguyên tố nhỏ hơn $K$ rồi chia dần $x$ cho các số nguyên tố đó thu được giá trị, rồi sẽ biết được số đó có phải là số $K$-factor hay không.

## Thuật toán

Đầu tiên ta tìm các số nguyên tố $\le K$.

Với mỗi số nguyên tố tìm được, gọi số nguyên tố hiện tại là $p$. Ta xét tất cả các bội của $p$ trong khoảng $[a,b]$. Có nhiều cách làm cho cái này.

Với mỗi bội, ta chia dần số đó cho $p$ sao cho không còn chia hết cho $p$ nữa. Ta có thể tối ưu thêm bằng cách thêm điều dừng nhỏ hơn $K$.

Ta xét lại các số đã được chia, ta bây giờ cần đếm số lượng số sau khi đã chia mà nhỏ hơn $K$ là xong.

## Code mẫu
```cpp=
/*
    nongvy the cutie :3
*/
#include <bits/stdc++.h>
using namespace std;

#define int long long
#define INF 1e18
#define MAX LLONG_MAX
#define MIN LLONG_MIN
#define MOD (int)1e9 + 7
#define f first
#define s second
#define pii pair<int, int>
#define vi vector<int>

void setIO(string name = "")
{
    ios_base::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
#ifndef ONLINE_JUDGE
    if (!name.empty())
    {
        freopen((name + ".INP").c_str(), "r", stdin);
        freopen((name + ".OUT").c_str(), "w", stdout);
    } else {
        freopen("inp.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    }
#endif
}
const int MAXN = 1e7 + 5;
bool sieve[MAXN + 5];
void init() {
    memset(sieve, true, sizeof(sieve));

    sieve[0] = sieve[1] = false;

    for(int i = 2; i * i <= MAXN; i++) {
        if(sieve[i]) {
            for(int j = i * i; j <= MAXN; j += i) {
                sieve[j] = false;
            }
        }
    }
}

int bs(int x, int a) {
    int l = 0, r = a;
    int res = a;
    while(l <= r) {
        int mid = (l + r) / 2;
        if(mid * x >= a) res = mid, r = mid - 1;
        else l = mid + 1;
    }

    return res;
}

void solve()
{
    init();
    int k, a, b;
    cin >> k >> a >> b;
    vi nums;
    for(int i = a; i <= b; i++) nums.push_back(i);
    vi pr;

    for(int i = 2; i <= k; i++) {
        if(sieve[i]) pr.push_back(i);
    }

    for(int x : pr) {
        int l = bs(x, a) * x;
        while(l <= b) {
            while(nums[l - a] % x == 0 && nums[l - a] > k) nums[l - a] /= x;
            l += x;
        }
    }

    int cnt = 0;

    for(int x : nums) cnt += (x <= k);
    cout << cnt << '\n';

}
signed main()
{
    setIO();
    int t = 1;
    // cin >> t;
    while (t--)
        solve();
}
```

