The sum problem
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13512 Accepted Submission(s): 4074
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]
//一开始想递归求解的思路就是错误的,因为n、m太大了,这里肯定是不能用递归来解答的。
//后来想到从前向后,设置两个变量标志数组起始位置和终止位置,进行一遍遍历即可: 将递归改为非递归!
//但是!! 超时!
代码:
#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #define N 1001000 int n,m; int main() { int i,j,k=0; //freopen("in.txt","r",stdin); while(scanf("%d %d",&n,&m)){ if(k) printf("\n"); if(n==m && n==0) break; int front=1,last=1;int num=1; while(front<=last){ if(num==m) printf("[%d,%d]\n",front,last); if(num<m){ last++; num=num+last; } else{ num=num-front; front++; } } k=1; } return 0; }
//之后又想,既然一遍遍历都超时,那肯定就是有什么公式在里面了,换句话说也就是这个题目是有技巧的,需要进一步约减计算步骤。
// 既然要约减,这里肯定就是要去减少枚举量,这样才能顺利解决。
//思路:
我们之前是枚举的区间开头和结尾! 现在我们枚举区间长度! 这样可以使枚举量降低一个层次!从而达到顺利解决问题的目的。
而当首项为1时,区间长度最长,可知区间最长为: int len=sqrt((double)(m)*2.0);
之后枚举区间长度来求解即可!
代码:
#include<iostream> using namespace std; #include<math.h> int main() { int n,m,i,j; while(scanf("%d%d",&n,&m) && (n||m)) { int len=sqrt((double)(m)*2.0); while(len) { int a=m/len-(len-1)/2; int b; if(a*len+(len-1)*len/2==m) { printf("[%d,%d]\n",a,a+len-1); } len--; }printf("\n"); } return 0; }
//下面是一开始递归的想法,想去递归求解,但因为n、m过大,肯定爆栈,觉得脑子抽抽了才会去写这个递归的代码...
错误代码:
#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #define N 1001000 int n,m; void Cha(int a,int b,int num){ if(a>b) ; else if(a>n || b>n) ; else{ if(num==m) printf("[%d,%d]\n",a,b); if(num>m) Cha(a+1,b,num-a); else Cha(a,b+1,num+b+1); } } int main() { int i,j,k=0; freopen("in.txt","r",stdin); while(scanf("%d %d",&n,&m)){ if(k) printf("\n"); if(n==m && n==0) break; int front=1,last=1; Cha(front,last,1); k=1; } return 0; }