123
题目描述
小蓝发现了一个有趣的数列, 这个数列的前几项如下:
1 , 1 , 2 , 1 , 2 , 3 , 1 , 2 , 3 , 4 , … 1,1,2,1,2,3,1,2,3,4, \ldots 1,1,2,1,2,3,1,2,3,4,…
小蓝发现, 这个数列前 1 1 1 项是整数 1 1 1 , 接下来 2 2 2 项是整数 1 1 1 至 2 2 2 , 接下来 3 3 3 项是整数 1 1 1 至 3 3 3 , 接下来 4 4 4 项是整数 1 1 1 至 4 4 4 , 依次类推。
小蓝想知道, 这个数列中, 连续一段的和是多少。
输入格式
输入的第一行包含一个整数 T T T, 表示询问的个数。
接下来 T T T 行, 每行包含一组询问, 其中第 i i i 行包含两个整数 l i l_{i} li 和 r i r_{i} ri, 表示 询问数列中第 l i l_{i} li 个数到第 r i r_{i} ri 个数的和。
输出格式
输出 T T T 行, 每行包含一个整数表示对应询问的答案。
输入样例
3
1 1
1 3
5 8
输出样例
1
4
8
提示
对于 10 % 10 \% 10% 的评测用例, 1 ≤ T ≤ 30 , 1 ≤ l i ≤ r i ≤ 100 1 \leq T \leq 30,1 \leq l_{i} \leq r_{i} \leq 100 1≤T≤30,1≤li≤ri≤100 。
对于 20 % 20 \% 20% 的评测用例, 1 ≤ T ≤ 100 , 1 ≤ l i ≤ r i ≤ 1000 1 \leq T \leq 100,1 \leq l_{i} \leq r_{i} \leq 1000 1≤T≤100,1≤li≤ri≤1000 。
对于 40 % 40 \% 40% 的评测用例, 1 ≤ T ≤ 1000 , 1 ≤ l i ≤ r i ≤ 1 0 6 1 \leq T \leq 1000,1 \leq l_{i} \leq r_{i} \leq 10^{6} 1≤T≤1000,1≤li≤ri≤106 。
对于 70 % 70 \% 70% 的评测用例, 1 ≤ T ≤ 10000 , 1 ≤ l i ≤ r i ≤ 1 0 9 1 \leq T \leq 10000,1 \leq l_{i} \leq r_{i} \leq 10^{9} 1≤T≤10000,1≤li≤ri≤109 。
对于 80 % 80 \% 80% 的评测用例, 1 ≤ T ≤ 1000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 1000,1 \leq l_{i} \leq r_{i} \leq 10^{12} 1≤T≤1000,1≤li≤ri≤1012 。
对于 90 % 90 \% 90% 的评测用例, 1 ≤ T ≤ 10000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 10000,1 \leq l_{i} \leq r_{i} \leq 10^{12} 1≤T≤10000,1≤li≤ri≤1012 。
对于所有评测用例, 1 ≤ T ≤ 100000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 100000,1 \leq l_{i} \leq r_{i} \leq 10^{12} 1≤T≤100000,1≤li≤ri≤1012 。
解题思路
数列中的每一个连续的部分可以看作一个小区间。
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 ...
每一个小区间都是一个 a1=1,d=1 的等差数列,且区间的长度也能构成等差数列。
由于 l,r ≤ 1012 ,即
( 1 + n ) n 2 ≥ 1 0 12 \frac{(1+n)n}{2}\ge10^{12} 2(1+n)n≥1012所以最多有 1414214 个小区间构成该数列,满足任意 l,r 都能落在里面。这意味着虽然我们不能直接查询某一位置的前缀和,但可以通过这些小区间来定位和计算某一位置的前缀和。
- 第 i 个区间的元素个数为 i。
- 定义 index[ i ] 表示前 i 个小区间的元素个数(1 ~ n 的和)。
则有:index[ i ]=index[i−1]+i 。- 定义 sum[ i ] 表示前 i 个小区间的和。则有:sum[ i ]=sum[i−1]+index[ i ]。
- 对于数列中任意位置 i ,一定存在一个最大的 j 满足 a[ j ]≤ i ,这表示第 i 个数落在第 j+1 区间内。
- 对于数列中任意位置 i,当它落在第 j+1 个区间,它是该区间第 k 个数,则它在数列中的前缀和为:sum[ j ]+index[ k ],其中 k=i−index[ j ]。
代码
#include<stdio.h>
#define N 1414215
long long index[N];
long long sum[N];
long long binarysearch(long long n){
int l=1,r=N;
while(l<=r){
int mid=(l+r)/2;
if(index[mid]>n)
r=mid-1;
else
l=mid+1;
}
return sum[l-1]+index[n-index[l-1]];
}
int main(){
for(int i=1;i<N;i++){
index[i]=index[i-1]+i;
sum[i]=sum[i-1]+index[i];
}
int t;
scanf("%d",&t);
while(t--){
long long l,r;
scanf("%lld %lld",&l,&r);
printf("%lld\n",binarysearch(r)-binarysearch(l-1));
}
return 0;
}