hdu2058

The sum problem

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 14190    Accepted Submission(s): 4259


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).input ends with N = M = 0.
 

Output
For each test case, print all the possible sub-sequence that its sum is M.The format is show in the sample below.print a blank line after each test case.
 

Sample Input
  
  
20 10 50 30 0 0
 

Sample Output
  
  
[1,4] [10,10] [4,8] [6,9] [9,11] [30,30]
 这题的大致意思就是给你两数,第一个是有多少项,第二个是和,问题要求是你要在这多少项中找到子数列使得和为第二个数,
就像你输入20 10;输出的结果是【1,4】1+2+3+4=10,【10,10】10=10;
所以你只需要找到这个数列的开始和结尾就好了,开始我用双层循环,没有异议的超时了,八嘎!
代码:
#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
int main()
{
	int m,n;
	int i,j;
	while(cin>>m>>n,m,n)
	{
		
		for(i=1;i<=n;i++)
		{
			long long sum=0;
			for(j=i;j<=n;j++)
			{
				sum+=j;
				if(sum==n)
				{
					cout<<'['<<i<<','<<j<<']'<<endl;
					break;
				}
			}
		}
		cout<<endl;
	}
	return 0;
}

好吧我承认我水,然后看了大神们的代码,才知道用等差数列公式变形做
Sn=(a1+aN)*n/2
    =(a1+a1+d(n-1))*n/2
    =a1*n+d(n-1)*n/2;

然后 a1=1,现在又可化简为Sn=n+(n-1)*n/2=(n+1)n/2;
由题意得M=Sn,N为项的个数,则N<=n(max)=sqrt(Sn*2)=sqrt(M*2);
因此原式M=Sn =a1*n+(n-1)n/2=a1*N+(N-1)N/2,可得a1*N=M-(N-1)N/2;

好吧这就可以做了;
代码:
#include <iostream>
#include<cmath>
using namespace std;

int main()
{
    int m,n;
    while(cin>>m>>n,m,n)
    {
        int len =(int )sqrt(n*2.0);
        int sum=0;
        for(;len>0;len--)
        {
            sum=n-len*(len-1)/2;
            if(sum%len==0)
            {
                cout<<'['<<sum/len<<','<<sum/len+len-1<<']'<<endl;
            }
        }
        cout<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值