1. 程式人生 > >HDU - 2058 - The sum problem

HDU - 2058 - The sum problem

total orm back spa ins gpo 大於 2.0 ...

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 從 1N 遍歷一邊,只要 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 }

HDU - 2058 - The sum problem