# 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(); } ```