三角数问题....在4秒内显示

时间:2009-08-14 21:05:53

标签: c++

  

三角形数字的序列是   通过添加自然生成   数字。所以第7个三角形数字   将是1 + 2 + 3 + 4 + 5 + 6 + 7 =   28.前十个任期将是:

     

1,3,6,10,15,21,28,36,45,55,   ...

     

让我们列出第一个因素   七个三角形数字:

 1: 1
 3: 1,3
 6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
     

我们可以看到28是第一个   三角形数量超过五个   除数。

     

给定整数n,显示第一个   具有至少n的三角形数   除数。

     

样本输入:5

     

输出28

     

输入约束:1< = n< = 320

我显然能够做到这个问题,但我使用了一个天真的算法:

  1. 获取 n

  2. 使用mod运算符查找三角形数字并检查它们的因子数。

  3. 但挑战是在输入后4秒内显示输出。在190和以上的高输入上,它花了将近15-16秒。然后我尝试将三角形数字及其因子数量先放入二维数组中,然后从用户处获取输入并搜索数组。但不知怎的,我无法做到:我遇到了很多处理器故障。请尝试使用此方法并粘贴代码。或者,如果有更好的方法,请告诉我。

11 个答案:

答案 0 :(得分:11)

这是一个提示:

根据Divisor function的除数是每个素因子的幂加1的乘积。例如,让我们考虑28的指数素数表示:

28 = 2 2 * 3 0 * 5 0 * 7 1 * 11 0功能 ...

每个指数加1的乘积是:(2 + 1)*(0 + 1)*(0 + 1)*(1 + 1)*(0 + 1)... = 6,果然,28有6个除数。

现在,考虑 n th 三角形数可以封闭形式计算为 n n 1)/ 2。我们可以简单地通过在每个位置加上指数来乘以指数素数形式的数字。除以2意味着减少两个地方的指数。

你知道我要去哪儿吗?

答案 1 :(得分:4)

好吧,你没有详细介绍你做了什么,但如果你没有想到它,我可以给你一个可以使用的优化......

如果您使用直接的方法尝试查找数字n的因子,通过使用mod运算符,您不需要检查所有数字< ñ。这显然需要进行n次比较......你可以上楼(sqrt(n))。对于您找到的每个因子,只需将n除以该数字,您就会得到共轭值,而不需要手动找到它。

例如:说n是15。

我们循环,先尝试1。是的,mod检查出来,所以这是一个因素。我们将n除以因子得到共轭值,所以我们做(15/1)= 15 ...所以15是一个因素。

接下来尝试2。不。然后3.是的,这也给了我们(15/3)= 5.

我们已经完成了,因为4是>地板(SQRT(N))。快速!

如果你没有想到它,这可能是你可以利用来改善你的时间......总的来说你从O(n)到O(sqrt(n))这是相当不错的(尽管数字很多)这个小的常数可能仍然很重。)

答案 2 :(得分:3)

我正在回到学校的编程竞赛中,那里有一些类似的问题,有一个运行时间限制。 “解决”它的团队如下:

1)用蛮力慢的方法解决它 2)写一个程序只打印出答案(你发现使用慢速方法),这将运行亚秒。

我认为这是假的,但他们赢了。

答案 3 :(得分:2)

请参阅Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n. (Formerly M2535 N1002)

然后选择您想要实现的语言,请参阅this

  

“...... Python

import math
def diminishing_returns(val, scale):
    if val < 0:
        return -diminishing_returns(-val, scale)
    mult = val / float(scale)
    trinum = (math.sqrt(8.0 * mult + 1.0) - 1.0) / 2.0
    return trinum * scale
     

...“

答案 4 :(得分:0)

首先,创建包含两列的表:Triangle_Number Count_of_Factors。

其次,从这个表中得到一个具有相同列的表,但只包含具有不同因子数的最低三角形数的320行。

快速查找第二张表。

答案 5 :(得分:0)

如果您解决了问题,则应该可以访问the thread on Project Euler in which people post their (some very efficient) solutions

如果您要复制并粘贴问题,请引用the source(除非您的老师偷了它);我是第二个Wouter van Niferick的评论。

答案 6 :(得分:0)

好吧,至少你有一位好教授。表现很重要。

由于你有一个可以完成这项工作的程序,你可以预先计算1 ... 320的所有答案。

将它们存储在一个数组中,然后只需下标到数组中即可获得答案。那将是非常快的。

答案 7 :(得分:0)

小心编译,获得年度最差代码:D

#include <iostream>

bool isPrime( unsigned long long number ){

    if( number != 2 && number  % 2 == 0 )
        return false;

    for( int i = 3;
        i < static_cast<unsigned long long>
        ( sqrt(static_cast<double>(number)) + 1 )
        ; i += 2 ){

        if( number % i == 0 )
            return false;
    }

    return true;
}

unsigned int p;
unsigned long long primes[1024];

void initPrimes(){

    primes[0] = 2;
    primes[1] = 3;
    unsigned long long number = 5;

    for( unsigned int i = 2; i < 1024; i++ ){

        while( !isPrime(number) )
            number += 2;

        primes[i] = number;
        number += 2;
    }

    return;
}


unsigned long long nextPrime(){

    unsigned int ret = p;

    p++;

    return primes[ret];
}

unsigned long long numOfDivs( unsigned long long number ){

    p = 0;
    std::vector<unsigned long long> v;
    unsigned long long prime = nextPrime(), divs = 1, i = 0;


    while( number >= prime ){

        i = 0;

        while( number % prime == 0 ){
            number /= prime;
            i++;
        }

        if( i )
            v.push_back( i );

        prime = nextPrime();
    }

    for( unsigned n = 0; n < v.size(); n++ )
        divs *= (v[n] + 1);

    return divs;
}

unsigned long long nextTriNumber(){

    static unsigned long long triNumber = 1, next = 2;

    unsigned long long retTri = triNumber;

    triNumber += next;
    next++;

    return retTri;
}

int main()
{
    initPrimes();

    unsigned long long n = nextTriNumber();
    unsigned long long divs = 500;

    while( numOfDivs(n) <= divs )
    n = nextTriNumber();

    std::cout << n;

    std::cin.get();
}

答案 8 :(得分:0)

def first_triangle_number_with_over_N_divisors(N):

    n = 4
    primes = [2, 3]
    fact = [None, None, {2:1}, {3:1}]

    def num_divisors (x):
        num = 1
        for mul in fact[x].values():
            num *= (mul+1)
        return num

    while True:

        factn = {}

        for p in primes:
            if p > n//2: break
            r = n // p
            if r * p == n:
                factn = fact[r].copy()
                factn[p] = factn.get(p,0) + 1

        if len(factn)==0:
            primes.append(n)
            factn[n] = 1

        fact.append(factn)

        (x, y) = (n-1, n//2) if n % 2 == 0 else (n, (n-1)//2)

        numdiv = num_divisors(x) * num_divisors(y)
        if numdiv >= N:
            print('Triangle number %d: %d divisors'
                   %(x*y, numdiv))
            break

        n += 1


>>> first_triangle_number_with_over_N_divisors(500)
Triangle number 76576500: 576 divisors

答案 9 :(得分:-1)

老兄这里是你的代码,快看看吧。它计算出除数大于500的第一个数字。

void main() {


long long divisors = 0;
long long nat_num = 0;
long long tri_num = 0;
int tri_sqrt = 0;

while (1) {

    divisors = 0;
    nat_num++;
    tri_num = nat_num + tri_num;
    tri_sqrt = floor(sqrt((double)tri_num));
    long long i = 0;

    for ( i=tri_sqrt; i>=1; i--) {

        long long remainder = tri_num % i;
        if ( remainder == 0 && tri_num == 1 ) {
            divisors++;
        }
        else if (remainder == 0 && tri_num != 1) {
            divisors++;
            divisors++;
        }
    }

    if (divisors >100) {
        cout <<"No. of divisors: "<<divisors<<endl<<tri_num<<endl;
    }
    if (divisors > 500)
        break;
}

 cout<<"Final Result: "<<tri_num<<endl;
 system("pause");
}

答案 10 :(得分:-1)

Boojum的回答促使我写下这个小程序。它似乎工作得很好,虽然它确实使用蛮力计算素数的方法。如何将所有自然数分解为素数分量都很简洁。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <vector>

//////////////////////////////////////////////////////////////////////////////

typedef std::vector<size_t> uint_vector;

//////////////////////////////////////////////////////////////////////////////

// add a prime number to primes[]
void
primeAdd(uint_vector& primes)
{
    size_t n;
    if (primes.empty())
    {
        primes.push_back(2);
        return;
    }
    for (n = *(--primes.end()) + 1; ; ++n)
    {
        // n is even -> not prime
        if ((n & 1) == 0) continue;

        // look for a divisor in [2,n)
        for (size_t i = 2; i < n; ++i)
        {
            if ((n % i) == 0) continue;
        }

        // found a prime
        break;
    }
    primes.push_back(n);
}

//////////////////////////////////////////////////////////////////////////////

void
primeFactorize(size_t n, uint_vector& primes, uint_vector& f)
{
    f.clear();
    for (size_t i = 0; n > 1; ++i)
    {
        while (primes.size() <= i) primeAdd(primes);
        while (f.size() <= i) f.push_back(0);
        while ((n % primes[i]) == 0)
        {
            ++f[i];
            n /= primes[i];
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

int
main(int argc, char** argv)
{
    // allow specifying number of TN's to be evaluated
    size_t lim = 1000;
    if (argc > 1)
    {
        lim = atoi(argv[1]);
    }
    if (lim == 0) lim = 1000;

    // prime numbers
    uint_vector primes;

    // factors of (n), (n + 1)
    uint_vector* f = new uint_vector();
    uint_vector* f1 = new uint_vector();

    // sum vector
    uint_vector sum;

    // prime factorize (n)
    size_t n = 1;
    primeFactorize(n, primes, *f);

    // iterate over triangle-numbers
    for (; n <= lim; ++n)
    {
        // prime factorize (n + 1)
        primeFactorize(n + 1, primes, *f1);

        while (f->size() < f1->size()) f->push_back(0);
        while (f1->size() < f->size()) f1->push_back(0);
        size_t numTerms = f->size();

        // compute prime factors for (n * (n + 1) / 2)
        sum.clear();
        size_t i;
        for (i = 0; i < numTerms; ++i)
        {
            sum.push_back((*f)[i] + (*f1)[i]);
        }
        --sum[0];
        size_t numFactors = 1, tn = 1;
        for (i = 0; i < numTerms; ++i)
        {
            size_t exp = sum[i];
            numFactors *= (exp + 1);
            while (exp-- != 0) tn *= primes[i];
        }

        std::cout
            << n << ". Triangle number "
            << tn << " has " << numFactors << " factors."
            << std::endl;

        // prepare for next iteration
        f->clear();
        uint_vector* tmp = f;
        f = f1;
        f1 = tmp;
    }

    delete f;
    delete f1;
    return 0;
}