题目描述
小蓝发现了一个有趣的数列, 这个数列的前几项如下:
1,1,2,1,2,3,1,2,3,4,…1,1,2,1,2,3,1,2,3,4,…
小蓝发现, 这个数列前 1项是整数 1 , 接下来 2 项是整数 1 至 2 , 接下来 3 项是整数 1 至
3 , 接下来 4 项是整数 1 至 4 , 依次类推。
小蓝想知道, 这个数列中, 连续一段的和是多少
输入格式
输入的第一行包含一个整数 T, 表示询问的个数。
接下来 T 行, 每行包含一组询问, 其中第 i 行包含两个整数 l i
和 r i, 表示 询问数列中第 l i个数到第 r i个数的和。
输出格式
输出 T 行, 每行包含一个整数表示对应询问的答案。
#include <bits/stdc++.h>
using namespace std;
long long n, l, r, ans, t1, t2, st, ed, k1, k2;
/*
前置知识点
前n项的和 (首项+末项)*项数/2
还有就是前缀和的求解公式
不会的可以看一下这个,通俗易懂(在B站看一下)
https://www.bilibili.com/video/BV1NX4y147G5/?spm_id_from=333.337.search-card.all.click&vd_source=cb3df04c833ffa8fd0d609d3e022adb4
二分的方式求解
这个自己搜所一下
1
1 2
1 2 3
1 2 3 4
......
fd求解的是这里面某个数值,使用二分的方式求解的
其他的使用图来解释
*/
//这一部分求解的是
long long fd(long long x)
{
long long l = 1, r = 10000000, ans;
while (l <= r)
{
long long mid = (l + r) / 2;
if (mid * (mid + 1) / 2 < x)
l = mid + 1;
else
{
r = mid - 1;
ans = mid;
}
}
return ans;
}
int main()
{
//这里是输入要看几个区间的值
scanf("%lld", &n);
while (n--)
{
//这里是看[l,r]区间的值
scanf("%lld%lld", &l, &r);
//这个使用二分的方式找到行的作用
st = fd(l), ed = fd(r);
//这个的作用就是找到本身数字的大小的方式
t1 = l - st * (st - 1) / 2;
t2 = r - ed * (ed - 1) / 2;
//这个是找前缀和的方式
k1 = (st - 1) * st * (st + 1) / 6; //求出两个行的前缀和
k2 = (ed - 1) * ed * (ed + 1) / 6;
//这个用图解释一下
cout << k2 - k1 + (t2 + 1)*t2 / 2 - (t1 - 1)*t1 / 2 << endl; //运算,把刚才处理掉的补上
}
}
前置知识