HDU-4342 History repeat itself 二分
先二分找到这个非平方数,然后对一个一个区间进行求和的预处理。要注意边界问题。
代码如下:
#include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; typedef long long Int; Int N, num; long long int sum[1000005]; Int bsearch(Int l, Int r) { Int mid, left; while (l <= r) { mid = (l + r) >> 1; left = mid - (int)floor(sqrt(double(mid))); if (N > left) { l = mid + 1; } else { r = mid - 1; } } return l; } void pre() { int lim = 1 << 16; for (int i = 1; i <= lim; ++i) { sum[i] = sum[i-1]+1LL * (2*i+1) * i; } } int main() { Int T, pos, s; long long int ans; pre(); scanf("%I64d", &T); while (T--) { ans = 0; scanf("%I64d", &N); pos = bsearch(1, 1LL<<32); s = (int)floor(sqrt(double (pos)))-1; ans += (s+1)*(pos - (s+1)*(s+1)+1); printf("%I64d %I64d\n", pos, ans + sum[s]); } return 0; }