HDU - 2058 - The sum problem
阿新 • • 發佈:2018-04-06
total orm back spa ins gpo 大於 2.0 ...
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代碼:
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
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 }
HDU - 2058 - The sum problem