• 题解报告:hdu 2058 The sum problem


    题目链接: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 }
  • 相关阅读:
    将1、2、3..10...变成01、02、03...10...
    idea启动项目时报错
    八锁现象
    友联
    通达OA 任意文件删除结合文件上传导致RCE漏洞复现
    Linux提权
    vulnhub靶机DC2记录
    ThinkPHP5.x 任意代码执行漏洞复现
    SaltStack远程命令执行漏洞复现(CVE-2020-11651、CVE-2020-11652)
    vulnhub靶机DC1记录
  • 原文地址:https://www.cnblogs.com/acgoto/p/8698415.html
Copyright © 2020-2023  润新知