HDU 2058 The sum problem (数学+暴力)

题意:给定一个N和M,N表示从1到N的连续序列,让你求在1到N这个序列中连续子序列的和为M的子序列区间。

析:很明显最直接的方法就是暴力,可是不幸的是,由于N,M太大了,肯定会TLE的。所以我们就想能不能优化一下,找一个范围。想到这是一个连续的序列而且是从1开始的,这不就是一个等差数列么,公差是1罢了。由求和公式得Sn = (a1+an) * n / 2;所以说n最大就是sqrt(M*2)(想一想为什么),因为a1+an 一定是大于n的。如果我们取区间的和,那么Sn = (ai+aj) * (j-i+1)/2;以上我们可得到一个方程,i+j = M/n(当然n|M),j-i+1 = n;所以我们可以解出i和j,其他的就简单了从n到1暴一遍就OK。

当我做完后我又看了网上的题解,我个去,写的比我简单多了。。。

他们是这么说的,等差数列的运用。Sn = (a1+an) * n / 2 = (a1 + a1 + (n - 1) * d)*n/2。

解题公式变形:(a+a+len)*(len+1)/2 = m => a = m/(len+1)-len/2 (m是已知条件,len的最大值为sqrt(2*m))。

代码如下:

这是我写的代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>

using namespace std;

int main(){
    int n, m;
    while(scanf("%d %d", &n, &m)){
        if(!n && !m)  break;
        m <<= 1;
        int len = (int)sqrt(m) + 1;

        while(--len){
            if(n > len && m % len == 0){
                if((len + m / len - 1) % 2)  continue;
                int j = (len + m / len - 1) / 2;
                if(j > n || j < 0)  continue;
                int i = m / len - j;
                if(i > n || i < 0)  continue;
                if(i > j)  swap(i, j);
                printf("[%d,%d]\n", i, j);
            }
        }
        printf("\n");
    }
    return 0;
}

下面是题解的代码:

#include <cstdio>
#include <cmath>
using namespace std;

int main()
{
    int n, m, a, len;
    while (scanf("%d%d", &n, &m) && (n || m))
    {
        len = (int)sqrt(2*m);
        while (len--)
        {
            a = m / (len + 1) - len / 2;
            if ((2*a+len) * (len+1) / 2 == m)
                printf("[%d,%d]\n", a, a+len);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-10-07 20:12:06

HDU 2058 The sum problem (数学+暴力)的相关文章

hdu 2058 The sum problem (数学问题)

题目意思: http://acm.hdu.edu.cn/showproblem.php?pid=2058 给出n和m,在小于n的数中,找出连续的序列,使其和为m,并从小到大输出. 题目分析: 第一次见这种题,就模拟,很显然超时了,后来在<短码之美>上看到了好的解决方法,和详细讲解,现在我只会用,不知道怎么说明白了,我也是醉了... AC代码: /** *@xiaoran */ #include<iostream> #include<cstdio> #include<

hdu 2058 The sum problem(简单因式分解,,)

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 <= 100000000

hdu - 2058 The sum problem (数学题)

http://acm.hdu.edu.cn/showproblem.php?pid=2058 求1-N多少个连续字段和等于M. 假设 从i开始长度为k的字段和等于M,那么 ( i+  i+k-1) * k/2=M即(2*i+k-1)*k==2M   那么 从k<= sqrt(2*M); i=M/k-(k-1)/2.这样通过从大到小枚举k的长度,并同时计算i的值判断和是否等于M,输出即可. 注意从(2*i+k-1)*k==2M这个式子得出的是k<=sqrt(2*M)而不是i,这样是为了方便计算,

HDU 2058 The sum 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).i

HDU - 2058 The sum problem(简单数学题)

题意:求出所有的情况,等差上去可以达到m值. 原来想着暴力搜索,但是题中的数据太大,所以时间超限. 百度了一下,发现可以套公式. 等差求和公式: Sn=(a1+aN)*n/2     =(a1+a1+d(n-1))*n/2     =a1*n+d(n-1)*n/2; 因为此处公差d=1,所以Sn=a1*n+(n-1)*n/2,当从第一项开始算起时(因本题首项为1,即a1=1时),Sn=M时的项的个数n最多; a1=1,现在又可化简为Sn=n+(n-1)*n/2=(n+1)n/2; 由题意得M=S

hdu 2058 The sum problem(数学题)

题意:求[1,n]的子区间,使得子区间的元素和为m 代码: #include<cstdio> #include<cstring> #include<cmath> using namespace std; int main() { int n,m; while(scanf("%d%d",&n,&m)&&(n||m)) { for(int j=(int)sqrt(2*m);j>=1;j--) { int i=(2*m

hdu 2576 Another Sum Problem

题目大意:求前n项和的前n项和. 数学推导题,f(n)=n*(n+1)*(n+2)/6 推导思路如下: #include"cstdio" #include"cstring" #include"cmath" #include"cstdlib" #include"iostream" #include"algorithm" #include"queue" using nam

hdu 4627 The Unsolvable Problem(暴力的搜索)

Problem Description There are many unsolvable problem in the world.It could be about one or about zero.But this time it is about bigger number. Given an integer n(2 <= n <= 109).We should find a pair of positive integer a, b so that a + b = n and [a

HDU 3699 A hard Aoshu Problem (暴力搜索)

题意:题意:给你3个字符串s1,s2,s3;要求对三个字符串中的字符赋值(相同的字符串进行相同的数字替换), 替换后的三个数进行四则运算要满足左边等于右边,求有几种解法. Sample Input 2 A A A BCD BCD B Sample Output 5 72 eg:ABBDE   ABCCC   BDBDE :令 A = 1, B = 2, C = 0, D = 4, E = 5 12245 + 12000 = 24245: 注意没有前导零!! #include<stdio.h>