zoukankan      html  css  js  c++  java
  • 如何高效的找到所有总和为 sn 的连续正整数数列。

    例如 sn = 100 时,总和为100 的连续正整数数列有

    100
    18 19 20 21 22
    9 10 11 12 13 14 15 16

    对于这种算法的设计,我们最容易想到的就是从 1 到 sn 循环遍历所有的数,对于每个数再循环计算是否以这个数为起点总和正好是sn。这种算法的时间复杂度大概是

    O(n*log2n), 也就是说如果这样计算,当 sn = 100万时,大概需要循环 2000万次左右。 这样做效率自然是比较低的。那么我们有没有比上述方法更高效的方法呢?答案是肯定的。

    首先我们看等差数列求和的公式:

    Sn=n(a1+an)/2=na1+n(n-1)/2

    从这个公式我们不难看出当 Sn 和 n  固定时求a1 是一个线性函数:

    a1 = (Sn – n(n-1)/2) / n

    有了这个函数,优化这个算法就很简单了,我们只要把 n  从 1 开始遍历,一直遍历到 (Sn – n(n-1)/2) < n 为止,就可以找到所有的符合条件的连续数列了,这个算法的算法复杂度为 2N 的平方根,也就是说当 Sn = 100 万时,只需要循环1414次就可以得到所有的数列。

    刚刚看到邀月的算法:  http://www.cnblogs.com/downmoon/archive/2011/03/05/1971400.html

    这个算法 sn = 100 万时,循环次数是 12970034 次,比我这个算法效率上要低将近1万倍。

    下面给出我的算法代码

            static void ListSequence(int sn)
            {
                //忽略 sn 不是正整数的情况
                if (sn <= 0)
                {
                    return;
                }
     
                int n = 1; //n 从1 开始遍历
     
                int m = sn - n * (n - 1) / 2; //m 为 Sn – n(n-1)/2
     
                while (m >= n) //当m < n 时即 Sn – n(n-1)/2 < n 时退出循环
                {
                    if (m % n == 0) //如果m 可以被 n 整除,则存在连续n个正整数序列总和为sn。
                    {
                        int a1 = m / n; //求a1
     
                        //打印符合条件的连续数列
                        for (int i = a1; i < a1 + n; i++)
                        {
                            Console.Write(string.Format("{0} ", i));
                        }
                        Console.WriteLine();
                    }
     
                    n++; //n 加1
                    m = sn - n * (n - 1) / 2; //下一个 m
                }
     
                Console.WriteLine("循环次数:{0}", n);
            }

    Sn = 100 时,运行结果:

    100
    18 19 20 21 22
    9 10 11 12 13 14 15 16
    循环次数:14

    下面给出 Sn 从 10 开始到 1000万时的循环次数。

    Sn 循环次数
    10 5
    100 14
    1000 45
    10000 141
    100000 447
    1000000 1414
    10000000 4472
  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/eaglet/p/1971391.html
Copyright © 2011-2022 走看看