高端建设网站公司哪家好竞价恶意点击报案
G33 整除分块(数论分块)_哔哩哔哩_bilibili
对于每个i, 1 <= i <= n n / i 下取整的值最多有2 * sqrt(n)种 并且数字x所在块的值为 n / (n / i)
这一题, 每个块中余数是一个以除数为公差的等差数列, 二分第k大的数可能为几即可 , 二分的思路与E题极为相似
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
struct info {int hi, lo, div;
};
bool cmp(info a, info b) {return a.hi < b.hi;
}void solve(){int n, k;cin >> n >> k;map<int, int> next;for(int i = 1; i <= n; ) {next[i] = n / (n / i);i = next[i] + 1;}vector<info> a;for(int i = 1; i <= n;) {int div = n / i;int hi = n % i;int lo = n % next[i];a.push_back({hi,lo,div});i = next[i] + 1;}ll ans = 0;auto check = [&] (int x) -> bool {int cnt = 0;ll res = 0;for(auto it : a) {if(x > it.hi) continue;int z = (it.hi - max(it.lo, x) ) / it.div + 1;cnt += z;res += (it.hi + it.hi - it.div * 1ll * (z - 1)) * z / 2;}ans = res - (cnt - k) * x;return cnt >= k;};int lo = -1, hi = n + 1;while(lo + 1 < hi) {int mid = lo + hi >> 1;if(check(mid)) lo = mid;else hi = mid;}check(lo);cout << ans << endl;}int main(){std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);int T = 1;//cin >> T;while(T--) solve();return 0;
}