参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll temp[1500000], sum[1500000]; //temp数组记录序号和,sum数组记录前缀和
ll cal(ll n) //计算自然数求和
{
return (n+1)*n/2;
}
int main()
{
ios::sync_with_stdio(false);
ll index = 1;
ll endL;
while(1) //打表法
{
temp[index] = temp[index-1] + index;
sum[index] = sum[index-1] + temp[index];
if(temp[index] > 1e12) //当序号和大于上限时退出
{
endL = index; //记录序号和退出时的下标,便于二分查找确立边界
break;
}
index++;
}
ll T;
cin >> T;
ll l, r, res;
for(ll i = 0; i < T; i++)
{
cin >> l >> r;
ll leftL = lower_bound(temp, temp+endL, l) - temp; //lower_bound二分法查找
ll rightL = lower_bound(temp, temp+endL, r) - temp;
res = sum[rightL-1] - sum[leftL-1]; //首先得到两个大段差
res -= cal(l-temp[leftL-1]-1); //其次减去左边界到上个大段结束点之间的前缀和
res += cal(r-temp[rightL-1]); //最后加上右边界到上个大段结束点之间的前缀和
cout << res << endl;
}
return 0;
}