码迷,mamicode.com
首页 > 其他好文 > 详细

题解报告:hdu 2058 The sum problem

时间:2018-04-02 23:52:11      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:子序列   --   计算   c++   sqrt   pac   个数   show   out   

题目链接: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

标签:子序列   --   计算   c++   sqrt   pac   个数   show   out   

原文地址:https://www.cnblogs.com/acgoto/p/8698415.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!