題解報告:hdu 2058 The sum problem
阿新 • • 發佈:2018-04-03
show AC out 求和 pan post 思考 its 題解報告
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2058
問題描述
給定一個序列1,2,3,...... N,你的工作是計算所有可能的子序列,其子序列的總和為M.
輸入
輸入包含多個測試用例。 每個情況包含兩個整數N,M(1 <= N,M <= 1000000000)。輸入以N = M = 0結束。
輸出
對於每個測試用例,打印其總和為M的所有可能的子序列。格式顯示在下面的示例中。在每個測試用例後打印一個空行。
示例輸入
20 10
50 30
0 0
示例輸出
[1,4]
[10,10]
[4,8]
[6,9]
[9,11]
[30,30]
解題思路:這道題要轉換一下角度來思考,否則會一直WA~_~。。
不妨假設i為區間左值,j為區間元素個數(j至少為1),則區間為[i,i+j-1]。
若這個區間合法,那麽由等差數列求和公式,得(i+(i+j-1))*j/2==M(1式),即(2*i+j-1)*j/2==M(2式),故得i=(2*M/j-j+1)/2,
將i,j代回2式,若1式成立則[i,i+j-1]滿足條件。註意j最小為1,(區間右值大於或等於區間左值),而由2式,得(j+2*i)*j=2*M,
由題目條件得i>=1,則j*j<=2*M,即j<=(int)sqrt(2*M)。綜上,遍歷區間長度j即可。
AC代碼:
1 #include<bits/stdc++.h> 2using namespace std; 3 int main() 4 { 5 int N,M,i,j;//數學規律,等差數列 6 while(cin>>N>>M && (N+M)){ 7 for(j=(int)sqrt(2*M);j>0;j--){ 8 i=(2*M/j-j+1)/2;//推導出來的公式 9 if(j*(2*i+j-1)/2==M)cout<<‘[‘<<i<<‘,‘<<i+j-1<<‘]‘<<endl;//把i,j分別代入推導出來的表達式看是否相等 10 } 11 cout<<endl;//每個測試後面空出一行 12 } 13 return 0; 14 }
題解報告:hdu 2058 The sum problem