CF1151C Problem for Nazar
CF1151C Problem for Nazar - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目并没有给出 \(r - l\) 的限制,这意味着 \(l = 1, r = 10^{18}\) 的查询也需要在我们能处理的范围之内。
那可放心差分:第 \(l\) 个数到第 \(r\) 个数所有和,就是前 \(r\) 个数的和减去前 \(l - 1\) 个数的和。前缀和一般都比区间和好处理。
前 \(r\) 个数一定可以拆分为两个子序列:一个长度为 \(p\) 的从 \(1\) 开始的连续奇数序列;一个长度为 \(q\) 的从 \(2\) 开始的连续偶数序列。
简单的数学知识可以推导得答案为 \(p^2 + q^2 + q\)。那么问题变成求解 \(p\) 和 \(q\)。
根据题意,把 \(r\) 分解为 \(2^0 + 2^1 + 2^2 + \cdots + 2^k +c\)。这个式子里,奇数项之和就是 \(p\),偶数项之和就是 \(q\)。
朴素的 \(\log r\) 分解就可以了。
时间复杂度 \(\mathcal{O}(\log r)\)。
/*
* @Author: crab-in-the-northeast
* @Date: 2022-10-17 16:42:44
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2022-10-17 16:50:53
*/
#include <bits/stdc++.h>
#define int long long
const int mod = (int)1e9 + 7;
inline int read() {
int x = 0;
bool flag = true;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
flag = false;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
if(flag)
return x;
return ~(x - 1);
}
inline int solve(int n) {
int p = 0, q = 0, t = 1;
for (int s = 1; s <= n; s <<= 1, t ^= 1) {
n -= s;
if (t)
(p += s) %= mod;
else
(q += s) %= mod;
}
if (t)
(p += n) %= mod;
else
(q += n) %= mod;
return (((p * p % mod + q * q % mod) % mod) + q) % mod;
}
signed main() {
int l = read(), r = read();
printf("%lld\n", (solve(r) - solve(l - 1) + mod) % mod);
return 0;
}