大家好,我是晴天学长,今天的算法题思想用到了枚举二分,数列的求和,题目不难,但是知识的思路的运用还是值得学习的,需要的小伙伴请自取哦!💪💪💪
1 )123
2) .算法思路
123
首先预处理(一个简单的前缀和)
1.用快读快输接收
2.循环for
3.接收两个数 x y
4.输出求出 S[y] - S[x-1]的前缀和
前缀和部分(输入k)
1.二分查找(一定存在)
l=1,r = 1500000;
用左不满足右满足法 注意mid= l+1;
找到r s[r]> k
r-- 满足条件块数
x = - s(r);
再次用等差数列求和 s(x)
返回 s(r)+s(x);
2.等差数列求和
Sn=n(a1+an)/2。
3).代码示例
package LanQiaoTest.二分;
import java.util.Scanner;
public class _123 {
static long[] S = new long[1500010];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
ready(S);//预处理
for (int i = 0; i < T; i++) {
long x = sc.nextLong();
long y = sc.nextLong();
System.out.println(check(y)-check(x-1));
}
}
//预处理
private static void ready(long[] S) {
long t = 0;
for (int i = 1; i <= 1500000; i++) {
t += i;
S[i] = S[i - 1] + t;
}
}
//等差数列求和
private static long Sn(long mid) {
return (mid * (1L + mid)) / 2;
}
//二分查找求和,找到k是属于那一块
private static long check(long k) {
int l = 1;
int r = 1500000;
while (l < r) {
int mid = (r - l) / 2 + l;
//是按照块的大小来对比的,就相当于mid是an(块)
if (Sn(mid) >= k) {
r = mid;
} else l = mid + 1;
}
r--;
k -=Sn(r);
return S[r] + Sn(k);
}
}
4).总结
- 利用等差数列分块。
- 用前缀和解决一块区域的和。