1. 程式人生 > >題解報告:hdu 2058 The sum problem

題解報告:hdu 2058 The sum problem

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>
 2
using 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