The sum problem
Given a sequence 1,2,3,…N, your job is to calculate all the possible sub-sequences that the sum of the sub-sequence is M.
Input
Input contains multiple test cases. each case contains two integers N, M( 1 <= N, M <= 1000000000).input ends with N = M = 0.
Output
For each test case, print all the possible sub-sequence that its sum is M.The format is show in the sample below.print a blank line after each test case.
Sample Input
20 10
50 30
0 0
Sample Output
[1,4]
[10,10]
[4,8]
[6,9]
[9,11]
[30,30]
该题在没有什么思路时会想到从首项为1开始减少长度求和,再以首项为2开始减少长度求和,以此类推暴搜。但题目的数据上限是10亿所以必然会超时的。
有暴搜就要用公式,有暴搜就要用技巧。减少范围搜。
1.从以1为首项来确定最多项数。从此项数开始递减搜索。
2.接下来用项数和数列的和来确定首项,也是由等差数列求和公式:
3.再把这个求出来的首项ax以及项数代入①式中看等不等于Sn。若相等则输出区间。
有人肯定会疑惑,你第2.步第3.步代过来代过去肯定相等不是一样的吗?不一样。先从第1.开始讲。
此公式是以1为首项算任意项数的和。而不能用任意一个数字为和去算项数,算出来也可能不是整数。取整后便是一个最接近的项数。把这个项数反代回去算出来的Sn是最接近我们之前用的Sn的。
同理地,用以下公式也不一定能算得一个整数的ax。
也就是说以ax为首项,一个项数为n的区间求出的和是客观存在那的。我们只是负责找到它,它们。也就是说ax、n、Sn三者是配套的。我们用一个Sn和不同的n去套,若套得的ax是小数,就是不符合条件的。套得的ax是整数就是符合条件的。
现在在回答上面那个问题,当算出来的ax是小数,取整后反代回去是算不出Sn的。
只有当ax是整数时反代回去才会和原来的Sn相等。这恰好就是那个判断条件。
以上分析均参考博客:https://blog.csdn.net/u010372095/article/details/16330583
感谢他的精彩分析!
#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
long long n, m, Ni, ax;///Ni(项数):Number of items。ax:项数减少后的首项。
while(scanf("%lld%lld", &n, &m) != EOF && (n + m != 0))
{
for(Ni = (long long)pow(m * 2.0, 0.5); Ni >=1; Ni--)
{
ax = ((2*m / Ni) + 1 - Ni) / 2;
if(((ax + Ni - 1 + ax) * Ni)/2 == m)///原博主这里用的公式是:ax*n + (n - 1)/2
printf("[%lld,%lld]\n", ax, ax + Ni - 1);
}
printf("\n");
}
return 0;
}
以上代码来自:https://blog.csdn.net/u010372095/article/details/16330583