#include #include #include #include using namespace std; typedef long long ll; // Sàng nguyên tố đến 40000 để phân tích số đến 10^9 const int MAX_PRIME = 40000; vector primes; void sieve() { vector is_prime(MAX_PRIME + 1, true); is_prime[0] = is_prime[1] = false; for (int p = 2; p * p <= MAX_PRIME; p++) { if (is_prime[p]) { for (int i = p * p; i <= MAX_PRIME; i += p) is_prime[i] = false; } } for (int p = 2; p <= MAX_PRIME; p++) { if (is_prime[p]) primes.push_back(p); } } // Hàm DFS liệt kê tất cả ước số >= W void get_divisors(int idx, ll current, const vector>& factors, ll W, vector& res) { if (idx == factors.size()) { if (current >= W) res.push_back((int)current); return; } ll p = 1; for (int i = 0; i <= factors[idx].second; ++i) { get_divisors(idx + 1, current * p, factors, W, res); p *= factors[idx].first; } } int main() { ios::sync_with_stdio(false); cin.tie(NULL); sieve(); int N; ll W; if (!(cin >> N >> W)) return 0; unordered_map weight_sums; for (int i = 0; i < N; ++i) { int w, v; cin >> w >> v; if (w >= W) weight_sums[w] += v; } unordered_map gcd_counts; gcd_counts.reserve(200000); for (auto const& [w, v] : weight_sums) { // Phân tích thừa số nguyên tố nhanh vector> factors; int temp = w; for (int p : primes) { if (p * p > temp) break; if (temp % p == 0) { int cnt = 0; while (temp % p == 0) { cnt++; temp /= p; } factors.push_back({p, cnt}); } } if (temp > 1) factors.push_back({temp, 1}); // Liệt kê các ước số vector divisors; get_divisors(0, 1, factors, W, divisors); for (int d : divisors) { gcd_counts[d] += v; } } ll ans = 0; for (auto const& [g, total_v] : gcd_counts) { ans = max(ans, total_v); } cout << ans << endl; return 0; }