OJ, VJ The sum problem——定区间内查找符合条件区间——等差数列公式在计算机中的巧妙应用

The sum problem

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]

该题在没有什么思路时会想到从首项为1开始减少长度求和,再以首项为2开始减少长度求和,以此类推暴搜。但题目的数据上限是10亿所以必然会超时的。

有暴搜就要用公式,有暴搜就要用技巧。减少范围搜。

1.从以1为首项来确定最多项数。从此项数开始递减搜索。
在这里插入图片描述
2.接下来用项数和数列的和来确定首项,也是由等差数列求和公式:
在这里插入图片描述

3.再把这个求出来的首项ax以及项数代入①式中看等不等于Sn。若相等则输出区间。

有人肯定会疑惑,你第2.步第3.步代过来代过去肯定相等不是一样的吗?不一样。先从第1.开始讲。


此公式是以1为首项算任意项数的和。而不能用任意一个数字为和去算项数,算出来也可能不是整数。取整后便是一个最接近的项数。把这个项数反代回去算出来的Sn是最接近我们之前用的Sn的。

同理地,用以下公式也不一定能算得一个整数的ax。
在这里插入图片描述
也就是说以ax为首项,一个项数为n的区间求出的和是客观存在那的。我们只是负责找到它,它们。也就是说ax、n、Sn三者是配套的。我们用一个Sn和不同的n去套,若套得的ax是小数,就是不符合条件的。套得的ax是整数就是符合条件的。

现在在回答上面那个问题,当算出来的ax是小数,取整后反代回去是算不出Sn的。

只有当ax是整数时反代回去才会和原来的Sn相等。这恰好就是那个判断条件。

以上分析均参考博客:https://blog.csdn.net/u010372095/article/details/16330583

感谢他的精彩分析!

#include<stdio.h>
#include<string.h>
#include<math.h>

int main()
{
    long long n, m, Ni, ax;///Ni(项数):Number of items。ax:项数减少后的首项。

    while(scanf("%lld%lld", &n, &m) != EOF && (n + m != 0))
        {
            for(Ni = (long long)pow(m * 2.0, 0.5); Ni >=1; Ni--)
            {
                ax = ((2*m / Ni) + 1 - Ni) / 2;
                if(((ax + Ni - 1 + ax) * Ni)/2 == m)///原博主这里用的公式是:ax*n + (n - 1)/2
                    printf("[%lld,%lld]\n", ax, ax + Ni - 1);
            }
            printf("\n");
        }
    return 0;
}

以上代码来自:https://blog.csdn.net/u010372095/article/details/16330583

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值