给出一个正整数N和长度L,找出一段长度大于等于L的连续非负整数,他们的和恰好为N。答案可能有多个,我们需要找出长度最小的那个。
例如 N = 18,L = 2:
5 + 6 + 7 = 18
3 + 4 + 5 + 6 = 18
都是满足要求的,但是我们输出更短的 5 6 7。
输入描述:
输入数据包括一行: 两个正整数N(1 ≤ N ≤ 1000000000),L(2 ≤ L ≤ 100)
输出描述:
从小到大输出这段连续非负整数,以空格分隔,行末无空格。如果没有这样的序列或者找出的序列长度大于100,则输出No
输入:18 2
输出:5 6 7
解题思路:
通过差值为1的等差数列求解,通过等差数列基本公式的推导可以得到等差数列首项a1 = (2N - (L-1)L) / (2 * N),而L的值是不能大于100的,所以可以直接求解 L~100 间有没有整数a1解,有的话直接输出就好了,超过100,直接输出No,注意输出的行末不能带有空格。
(1)目的:找到一个从某个数字开始 以1为公差、长度为L 的等差数列的和。
(2)从a1开始、以d为差、长度为n的等差数列的求和公式,此题中 d = 1:
(3)只要能找到一个整数a1作为起始数值,即得:
N为已知,只需要根据n来求得a1。从L开始,依次遍历所有n的可能(从L到100),并检查相应求得的数值是否为整数即可。
/*
找到一个从某个数字开始以1为差长度为L的等差数列的和。
从a1开始以d为差长度为n的等差数列的求和公式;Sn = (a1 + (a1 + (n-1)d))*n/2
所以只要能找到一个整数a1作为起始数值:
a1 = (2*N - (l-1)*l) / (2*l)
N为已知,只需要根据l来求得a.
可以从L开始,依次遍历所有l的可能(从L到100),并检查相应求得的数值是否为整数即可。
*/
import java.util.*;
import java.util.Scanner;
public class SubArraySum {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int N = sc.nextInt();
int L = sc.nextInt();
boolean flag = false; // 标志符,判断是否有解
for(int i = L; i <= 100; i ++) {
if((2*N - (i - 1) * i) % (2*i) == 0) {
flag = true;
int a1 = (2*N - (i - 1) * i) / (2*i);
// 相当于存在a1,现在只需要判断a1是否为正整数,如果满足输出后续的元素,此时i为序列长度
if(a1 < 0) {
continue;
}
// 注意输出的时候末尾不能有空格,因此最后一位元素单个输出
for(int j = 0; j < i - 1; j ++) {
int aj = a1 + j;
System.out.print(aj + " ");
}
System.out.print(a1 + i - 1);
break;
}
}
if(flag == false) {
System.out.print("No");
}
}
sc.close();
}
}