计算1 <= n <= 10000的三元组

时间:2019-09-25 10:39:01

标签: c unique triplet

对于给定的数字,我必须输出有多少个三胞胎组成这个数字。还有1 + 1 + 8 = 8 + 1 + 1 = 1 + 8 + 1。

以下代码由用户Klutt提供。我试过了,的确,除了大量外,它确实有效。

int n;      /* to store the number */
long i=0;   /* counter (long, just to be sure) */

scanf("%d", &n);

/* makes triplets [a, b, c] and looks if the sum of those numbers is equal to the 
 * given number.
 */
for(int a=1; a<n; a++) {
    for(int b=a; b<n; b++) {
        for(int c=b; c<n; c++) {
            if(a+b+c == n) {
                i++;
            };
        };
    };
};

由于较长的CPU时间,我尝试将变量更改为unsigned int和unsigned long,并将for循环更改为其他类型的循环,以查看它们中的任何一个对CPU时间都有影响。

(我对如何真正影响这次一无所知。我的编码经验也几乎为0。)

但是,例如,当我插入一个大于1000的数字时,要花10秒钟以上的时间才能计算出答案。

2 个答案:

答案 0 :(得分:0)

您可以进行简单的暴力破解。对于大量用户来说这很慢,但是很容易实现。

int no_triplets=0;
for(int i=1; i<n; i++)
    for(int j=1; j<n; j++)
        for(int k=1; k<n; k++)
            if(i+j+k == n)
                no_triplets++;

printf("%d\n", no_triplets);

有很多方法可以改善这种非常简单的算法。例如,最简单的方法之一是使ijk的循环转到n-2n-in-(i+j) 。当你在的时候。将jk的起始值分别更改为ij。您还可以通过一些基本数学进行优化。例如,给定ijn,您可以通过k计算k=n-(i+j)。从您的问题来看,假设ijk应该大于零似乎是合理的。因此,通过使用一些数学运算和第一个优化,我们可以重写为:

int no_triplets=0;
for(int i=1; i<n-2; i++) {
    for(int j=i; j<n-i; j++) {
        int k=n-(i+j);
        if(k>0)
            no_triplets++;
    }
}

答案 1 :(得分:0)

这里您要问的基本上是数学问题,而不是编程问题。您要计算的值有一个简单的封闭形式表示形式。

我没有尝试直接导出公式,而是采取了一种捷径并搜索了{{3中的前几个非平凡值(1,1,2,3,4,5,7,8,10) }} –我立即在Online Encyclopedia of Number Sequences中找到了一个匹配项。

所述百科全书对此a(n) = round( (n+3)^2/12 )序列给出了封闭形式的表示。在C语言中,考虑到序列的偏移量后,可以简单地表示为i = n*n/12