123【蓝桥杯国赛】

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 1T30,1liri100

对于 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 1T100,1liri1000

对于 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} 1T1000,1liri106

对于 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} 1T10000,1liri109

对于 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} 1T1000,1liri1012

对于 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} 1T10000,1liri1012

对于所有评测用例, 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} 1T100000,1liri1012

解题思路

数列中的每一个连续的部分可以看作一个小区间。

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)n1012所以最多有 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值