The sum problem
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 29639 Accepted Submission(s): 8889
Problem Description
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]
----------------------------------------------------------------------------------------------------------------------------
直接暴力的复杂度O(n^2),1000000000数据量铁定会超时。
这里用到了等差数列公式: ( 首项 + 末项 ) * 项数 / 2 = 和
设 i 为 首项, j 为项数, M 为和,则末项就是 i+j-1,那么能推导出 [ i + ( i + j - 1 ) ] * j / 2 = M
那么现在只要求出 i, 那么 j 也就知道了。
继续推导式子变成:i = ( 2 * M / j - j + 1 ) / 2
题目中 j 是给了范围的(从 1 ~ N)。
那么只要将 j 从 1 到 N 遍历一边,只要 i 大于 0 就是一个结果啦,
可惜这样还是会超时。。
我们可以再将 j 的遍历范围优化一下:
根据题意, i 一定是 大于等于 1 的, 将 [ i + ( i + j - 1 ) ] * j / 2 = M 整理一下可以得出 j ^ 2 + j = 2M
那么 j 只要遍历到 sqrt( 2 * M ) 就可以了。
附AC代码:
1 #include <iostream> 2 #include <vector> 3 #include <cmath> 4 #include <cstdio> 5 using namespace std; 6 int n, m; 7 int main(){ 8 //freopen("in.cpp", "r", stdin); 9 double i; 10 while(cin >> n >> m && n+m){ 11 for(int j=(int)sqrt(2*m); j>=1; --j){ 12 i = (2.0*m/j - j + 1)/2; 13 if(i>0 && i - (int)i == 0){ 14 printf("[%.0lf,%.0lf]\n", i, i+j-1); 15 } 16 } 17 cout << endl; 18 } 19 return 0; 20 }