อินทิกรัสามเหลี่ยมและอินทิกรัลอินทิกรัล


15

พิจารณาABCสามเหลี่ยมที่แต่ละด้านมีความยาวเต็ม ( สามเหลี่ยมหนึ่ง ) กำหนดค่ามัธยฐานของABCให้เป็นส่วนของเส้นตรงจากจุดสุดยอดไปจนถึงจุดกึ่งกลางของฝั่งตรงข้าม ในภาพด้านล่างส่วนของเส้นสีแดงแสดงถึงค่ามัธยฐาน โปรดทราบว่าสามเหลี่ยมใด ๆ ที่ระบุมีค่ามัธยฐานสามค่า

triangle_medians

ให้nเป็นจำนวนเต็มบวก มีอินทิกรัลไม่รูปสามเหลี่ยมจำนวนกี่ตัวที่มีความยาวด้านละน้อยกว่าหรือเท่ากับnมีค่ามัธยฐานอินทิกรัลอย่างน้อยหนึ่งค่า

ท้าทาย

จงเขียนโปรแกรมเพื่อคำนวณจำนวนสามเหลี่ยมหนึ่งที่มีค่ามัธยฐานหนึ่งอย่างน้อยหนึ่งสำหรับกำหนดความยาวสูงสุดด้านn คำสั่งของความยาวด้านนั้นไม่สำคัญเช่น <6,6,5> แสดงถึงสามเหลี่ยมเดียวกันกับ <5,6,6> และควรนับเพียงครั้งเดียว ยกเว้นรูปสามเหลี่ยมที่เสื่อมสภาพเช่น <1,2,3>

เกณฑ์การให้คะแนน

n ที่ใหญ่ที่สุดซึ่งโปรแกรมของคุณสามารถสร้างจำนวนสามเหลี่ยมใน60 วินาทีในเครื่องของฉันคือคะแนนของคุณ โปรแกรมที่มีคะแนนสูงสุดจะเป็นผู้ชนะ เครื่องของฉันคือ Sony Vaio SVF14A16CLB, Intel Core i5, 8GB RAM

ตัวอย่าง

ให้T ( N ) เป็นโปรแกรมที่มีการป้อนข้อมูลN

T(1) = 0
T(6) = 1
T(20) = 27
T(22) = 34

โปรดทราบว่าT (1) = T (2) = T (3) = T (4) = T (5) = 0 เพราะไม่มีการรวมกันของส่วนที่สำคัญจะให้ค่ามัธยฐานอินทิกรัล อย่างไรก็ตามเมื่อเราไปถึง 6 เราจะเห็นว่าหนึ่งในค่ามัธยฐานของรูปสามเหลี่ยม <5,5,6> คือ 4 ดังนั้นT (6) = 1

โปรดทราบว่าT (22) เป็นค่าแรกที่การนับซ้ำจะกลายเป็นปัญหา: รูปสามเหลี่ยม <16,18,22> มีค่ามัธยฐาน 13 และ 17 (และ 2sqrt (85))

การคำนวณค่ามัธยฐาน

ค่ามัธยฐานของรูปสามเหลี่ยมสามารถคำนวณได้จากสูตรดังต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

Current top score: Sp3000 - 7000 points - C

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Doorknob

คำตอบ:


7

C, กำลังดุร้าย - n = 6080

นี่เป็นพื้นฐานมากกว่าคู่แข่งที่ร้ายแรง แต่อย่างน้อยก็ควรเริ่มต้นสิ่งต่าง ๆ

n = 6080 สูงเท่ากับที่ฉันได้รับในหนึ่งนาทีของรันไทม์บนเครื่องของตัวเองซึ่งเป็น MacBook Pro กับ Intel Core i5 ผลลัพธ์ที่ฉันได้รับสำหรับค่านี้คือ:

15041226

รหัสนี้เป็นเดรัจฉานกำลังบริสุทธิ์ มันระบุสามเหลี่ยมทั้งหมดภายในขนาด จำกัด และการทดสอบสำหรับเงื่อนไข:

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

static inline int isSquare(int v) {
    int s = (int)(sqrtf((float)v) + 0.5f);
    return s * s == v;
}

static inline int isMedian(int v) {
    return v % 4 == 0 && isSquare(v / 4);
}

int main(int argc, char* argv[]) {
    int n = atoi(argv[1]);
    int nTri = 0;
    int a, b, c;

    for (c = 1; c <= n; ++c) {
        for (b = (c + 1) / 2; b <= c; ++b) {
            for (a = c - b + 1; a <= b; ++a) {
                if (isMedian(2 * (b * b + c * c) - a * a) ||
                    isMedian(2 * (a * a + c * c) - b * b) ||
                    isMedian(2 * (a * a + b * b) - c * c)) {
                    ++nTri;
                }
            }
        }
    }

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

    return 0;
}

ขึ้นอยู่กับคอมไพเลอร์คุณสามารถเพิ่ม + ได้เร็วขึ้นจากการใช้lrintf()หรือ(int)roundf()แทนที่จะเพิ่ม 0.5f และใช้การตัดทอนเริ่มต้น บางครั้งคุณจำเป็นต้องใช้-ffast-mathเพื่อให้ได้cvtss2siคำสั่งเดียว inlines GCC lrintf()และsqrtfมีเพียง-fno-math-errnoเพื่อให้คุณได้รับ asm ที่มีประสิทธิภาพ: godbolt.org/g/E3hncQ (ฉันใช้-march=ivybridgeเพราะนั่นคือซีพียูของ OP) ด้วย-ffast-mathเสียงดังกราวเปลี่ยน sqrt เป็นซ้ำ rsqrt + Newton; IDK ถ้าชนะ
Peter Cordes

roundfอ๊ะมักจะไม่ ใช้(int)nearbyintf()ถ้าlrintf()ไม่ได้อยู่ในบรรทัดเพราะมันใช้โหมดการปัดเศษในปัจจุบันแทนโหมดแปลก ๆ stackoverflow.com/questions/37620659/…
Peter Cordes

6

C ประมาณ6650 6900

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

static inline int is_square(int n) {
    if ((n&2) != 0 || (n&7) == 5 || (n&11) == 8) {
        return 0;
    }

    int s = (int) (sqrtf((float) n) + 0.5f);
    return (s*s == n);
}

int main(int argc, char **argv) {
    int n = atoi(argv[1]);
    int count = 0;

    for (int a = 1; a <= n; ++a) {
        if (a&1) {
            for (int b = (a+1)/2; b <= a; ++b){
                if (b&1) {
                    for (int c = a-b+2; c <= b; c += 2) {
                        if (is_square((a*a + b*b)/2 - (c*c)/4)) {
                            ++count;
                        }
                    }
                } else {
                    for (int c = a-b+2; c <= b; c += 2) {
                        if (is_square((a*a + c*c)/2 - (b*b)/4)) {
                            ++count;
                        }
                    }
                }
            }
        } else {
            for (int b = (a+1)/2; b <= a; ++b){
                if (b&1) {
                    for (int c = a-b+2; c <= b; c += 2) {
                        if (is_square((b*b + c*c)/2 - (a*a)/4)) {
                            ++count;
                        }
                    }
                } else {
                    for (int c = a-b+2; c <= b; c += 2) {
                        if (is_square((b*b + c*c)/2 - (a*a)/4) ||
                            is_square((c*c + a*a)/2 - (b*b)/4) ||
                            is_square((a*a + b*b)/2 - (c*c)/4)) {
                            ++count;
                        }
                    }
                }
            }
        }
    }

    printf("%d\n", count);
    return 0;
}

ฉันไม่ค่อยได้ใช้ C บ่อยนัก แต่ด้วยจำนวนเลขคณิตที่เกิดขึ้นดูเหมือนว่าเป็นทางเลือกที่ดีของภาษา อัลกอริทึมหลักคือแรงเดรัจฉานเช่นคำตอบของ @ RetoKoradiแต่มีการเพิ่มประสิทธิภาพง่าย ๆ ไม่กี่ ฉันไม่แน่ใจว่าค่าของเราจะเทียบเคียงได้เนื่องจากคอมพิวเตอร์ของ @ RetoKoradi ดูเหมือนจะเร็วกว่าของฉัน

การเพิ่มประสิทธิภาพที่สำคัญคือการข้ามการ% 4ตรวจสอบอย่างสมบูรณ์ จตุรัสจำนวนเต็มn*nเป็น 0 หรือ 1 โมดูโล 4 ขึ้นอยู่กับว่าnตัวเองเป็นโมดูโล 0 หรือ 1 ดังนั้นเราสามารถดูความเป็นไปได้ทั้งหมดสำหรับ(x, y, z) % 2:

x%2  y%2  z%2    (2*(x*x+y*y) - z*z) % 4
----------------------------------------
 0    0    0              0
 0    0    1              3
 0    1    0              2
 0    1    1              1
 1    0    0              2
 1    0    1              1
 1    1    0              0
 1    1    1              3

สะดวกมีเพียงสองกรณีที่จะต้องพิจารณา: (0, 0, 0)และ(1, 1, 0)ซึ่งเมื่อพิจารณาจากทั้งสองด้านแรกa, bนั้นเท่ากับด้านที่สามที่cมีความเท่าเทียมกันa^b:

 a%2   b%2         c%2 must be
 -----------------------------
  0     0               0
  0     1               1
  1     0               1
  1     1               0

a^bมีความเท่าเทียมกันเหมือนกันa-bดังนั้นแทนที่จะค้นหาจากc = a-b+1และขึ้นไปทีละ 1 นี่จะช่วยให้เราค้นหาc = a-b+2และเพิ่มขึ้น 2 วินาที

การเพิ่มประสิทธิภาพอื่นมาจากข้อเท็จจริงที่ว่าใน(1, 1, 0)กรณีนี้เราต้องเรียก is_square เพียงครั้งเดียวเนื่องจากมีการเปลี่ยนแปลงเพียงครั้งเดียว นี่เป็นกรณีพิเศษในรหัสโดยการยกเลิกการค้นหา

การปรับให้เหมาะสมอื่น ๆ ที่รวมอยู่นั้นเป็นเพียงis_squareฟังก์ชั่นด่วน

-std=c99 -O3รวบรวมทำด้วย

(ขอบคุณ @RetoKoradi สำหรับการชี้ให้เห็นว่า0.5ใน is_square จำเป็นต้อง0.5fหลีกเลี่ยงการแปลงสองครั้ง)


1
น้อยมาก แต่คุณอาจต้องการที่จะใช้0.5fแทนใน0.5 เป็นค่าคงที่ของประเภทดังนั้นนิพจน์จะสร้างค่าสองเท่าเมื่อคุณเพิ่มรวมถึงการแปลงประเภทจากเป็นสำหรับคำอื่น ๆ is_square()0.5double0.5floatdouble
Reto Koradi

@RetoKoradi อาขอบคุณ - นั่นเป็นเรื่องที่ไม่น่าแปลกใจfเลย
Sp3000

2

เฟลิกซ์ไม่ทราบ

fun is_square(v: int) => let s = int$ sqrt$ v.float + 0.5f in s*s == v;
fun is_median(v: int) => v % 4 == 0 and (v/4).is_square;

proc main() {
    n := int$ System::argv 1;
    var ntri = 0;

    for var c in 1 upto n do
        for var b in (c+1)/2 upto c do
            for var a in c - b + 1 upto b do
                if is_median(2*(b*b+c*c)-a*a) or
                   is_median(2*(a*a+c*c)-b*b) or
                   is_median(2*(a*a+b*b)-c*c) do ++ntri; done
            done
        done
    done

    ntri.println;
}

main;

โดยทั่วไปแล้วพอร์ตของคำตอบ C แต่มันเร็วกว่าทดสอบclang -O3และicc -O3ด้วย เฟลิกซ์และนิมเป็นเพียงสองภาษาที่ฉันรู้จักซึ่งสามารถเอาชนะ C และ C ++ ได้อย่างมีประสิทธิภาพ ฉันกำลังทำงานกับรุ่นขนาน แต่มันจะเป็นบิตจนกว่าจะเสร็จสิ้นดังนั้นฉันตัดสินใจที่จะโพสต์นี้ไป

ฉันใส่ "ไม่ทราบ" ด้วยเพราะคอมพิวเตอร์ของฉันไม่จำเป็นต้องเร็วที่สุดในโลก ...

คำสั่งที่ใช้ในการสร้าง:

flx --usage=hyperlight -c --static -o sl0 sl0.flx

C ++ ที่สร้างขึ้นนั้นค่อนข้างน่าสนใจที่จะดู:

//Input file: /home/ryan/golf/itri/sl0/sl0.flx
//Generated by Felix Version 15.04.03
//Timestamp: 2015/7/16 20:59:42 UTC
//Timestamp: 2015/7/16 15:59:42 (local)
#define FLX_EXTERN_sl0 FLX_EXPORT
#include "sl0.hpp"
#include <stdio.h>
#define comma ,

//-----------------------------------------
//EMIT USER BODY CODE
using namespace ::flxusr::sl0;

//-----------------------------------------
namespace flxusr { namespace sl0 {

//-----------------------------------------
//DEFINE OFFSET tables for GC
#include "sl0.rtti"
FLX_DEF_THREAD_FRAME
//Thread Frame Constructor
thread_frame_t::thread_frame_t(
) :
  gcp(0),
  shape_list_head(&thread_frame_t_ptr_map)
{}

//-----------------------------------------
//DEFINE FUNCTION CLASS METHODS
#include "sl0.ctors_cpp"
//------------------------------
//C PROC <61624>: _init_
void _init_(FLX_APAR_DECL_ONLY){
  int _i63436_v63436_s;
  int _i63435_v63435_s;
  int s;
  int a;
  int b;
  int c;
  int ntri;
  int n;
      n = static_cast<int>(::std::atoi((::std::string(1<0||1>=PTF argc?"":PTF argv[1])).c_str())); //assign simple
      ntri = 0; //assign simple
      c = 1; //assign simple
    _63421:;
      if(FLX_UNLIKELY((n < c))) goto _63428;
      b = (c + 1 ) / 2 ; //assign simple
    _63422:;
      if(FLX_UNLIKELY((c < b))) goto _63427;
      a = (c - b ) + 1 ; //assign simple
    _63423:;
      if(FLX_UNLIKELY((b < a))) goto _63426;
/*begin match*/
/*match case 1:s*/
      s  = static_cast<int>((::std::sqrt(((static_cast<float>(((2 * (b * b  + (c * c ) )  - (a * a ) ) / 4 ))) + 0.5f ))))/*int.flx: ctor*/; //init
/*begin match*/
/*match case 1:s*/
      _i63435_v63435_s  = static_cast<int>((::std::sqrt(((static_cast<float>(((2 * (a * a  + (c * c ) )  - (b * b ) ) / 4 ))) + 0.5f ))))/*int.flx: ctor*/; //init
/*begin match*/
/*match case 1:s*/
      _i63436_v63436_s  = static_cast<int>((::std::sqrt(((static_cast<float>(((2 * (a * a  + (b * b ) )  - (c * c ) ) / 4 ))) + 0.5f ))))/*int.flx: ctor*/; //init
      if(!((((2 * (b * b  + (c * c ) )  - (a * a ) ) % 4  == 0) && (s * s  == (2 * (b * b  + (c * c ) )  - (a * a ) ) / 4 )  || (((2 * (a * a  + (c * c ) )  - (b * b ) ) % 4  == 0) && (_i63435_v63435_s * _i63435_v63435_s  == (2 * (a * a  + (c * c ) )  - (b * b ) ) / 4 ) ) ) || (((2 * (a * a  + (b * b ) )  - (c * c ) ) % 4  == 0) && (_i63436_v63436_s * _i63436_v63436_s  == (2 * (a * a  + (b * b ) )  - (c * c ) ) / 4 ) ) )) goto _63425;
      {
      int* _tmp63490 = (int*)&ntri;
      ++*_tmp63490;
      }
    _63425:;
      if(FLX_UNLIKELY((a == b))) goto _63426;
      {
      int* _tmp63491 = (int*)&a;
      ++*_tmp63491;
      }
      goto _63423;
    _63426:;
      if(FLX_UNLIKELY((b == c))) goto _63427;
      {
      int* _tmp63492 = (int*)&b;
      ++*_tmp63492;
      }
      goto _63422;
    _63427:;
      if(FLX_UNLIKELY((c == n))) goto _63428;
      {
      int* _tmp63493 = (int*)&c;
      ++*_tmp63493;
      }
      goto _63421;
    _63428:;
      {
      _a12344t_63448 _tmp63494 = ::flx::rtl::strutil::str<int>(ntri) + ::std::string("\n") ;
      ::flx::rtl::ioutil::write(stdout,_tmp63494);
      }
}

//-----------------------------------------
}} // namespace flxusr::sl0
//CREATE STANDARD EXTERNAL INTERFACE
FLX_FRAME_WRAPPERS(::flxusr::sl0,sl0)
FLX_C_START_WRAPPER_PTF(::flxusr::sl0,sl0,_init_)

//-----------------------------------------
//body complete

2

C # (ประมาณ 11000?)

using System;
using System.Collections.Generic;

namespace PPCG
{
    class PPCG53100
    {
        static void Main(string[] args)
        {
            int n = int.Parse(args[0]);
            Console.WriteLine(CountOOE(n) + CountEEE(n));
        }

        static int CountOOE(int n)
        {
            // Maps from a^2 + b^2 to (b - a, a + b), which are the exclusive bounds on c.
            IDictionary<int, List<Tuple<int, int>>> pairs = new Dictionary<int, List<Tuple<int, int>>>();

            for (int a = 1; a <= n; a += 2)
            {
                int k = 2 * a * a;
                for (int b = a; b <= n; b += 2, k += 4 * (b - 1))
                {
                    List<Tuple<int, int>> prev;
                    if (!pairs.TryGetValue(k, out prev)) pairs[k] = prev = new List<Tuple<int, int>>();
                    prev.Add(Tuple.Create(b - a, a + b));
                }
            }

            int max = 2 * n * n;
            int count = 0;
            for (int x = 1; x <= n >> 1; x++)
            {
                int k = 4 * x * x;
                for (int y = x; y <= n; y++, k += 4 * y - 2)
                {
                    if (k > max) break;
                    List<Tuple<int, int>> ab;
                    if (pairs.TryGetValue(k, out ab))
                    {
                        foreach (var pair in ab)
                        {
                            // Double-counting isn't possible if a, b are odd.
                            if (pair.Item1 < x << 1 && x << 1 < pair.Item2)
                            {
                                count++;
                            }
                            if (x != y && y << 1 <= n && pair.Item1 < y << 1 && y << 1 < pair.Item2)
                            {
                                count++;
                            }
                        }
                    }
                }
            }

            return count;
        }

        static int CountEEE(int n)
        {
            // Maps from a^2 + b^2 to (b - a, a + b), which are the exclusive bounds on c.
            IDictionary<int, List<Tuple<int, int>>> pairs = new Dictionary<int, List<Tuple<int, int>>>();

            for (int a = 2; a <= n; a += 2)
            {
                int k = 2 * a * a;
                for (int b = a; b <= n; b += 2, k += 4 * (b - 1))
                {
                    List<Tuple<int, int>> prev;
                    if (!pairs.TryGetValue(k, out prev)) pairs[k] = prev = new List<Tuple<int, int>>();
                    prev.Add(Tuple.Create(b - a, a + b));
                }
            }

            // We want to consider m in the range [1, n] and c/2 in the range [1, n/2]
            // But to save dictionary lookups we can scan x in [1, n/2], y in [x, n] and consider both ways round.
            int max = 2 * n * n;
            int count = 0;
            for (int x = 1; x <= n >> 1; x++)
            {
                int k = 4 * x * x;
                for (int y = x; y <= n; y++, k += 4 * y - 2)
                {
                    if (k > max) break;
                    List<Tuple<int, int>> ab;
                    if (pairs.TryGetValue(k, out ab))
                    {
                        foreach (var pair in ab)
                        {
                            // (c1, m1) = (2x, y)
                            // (c2, m2) = (2y, x)

                            int a = (pair.Item2 - pair.Item1) / 2, b = (pair.Item2 + pair.Item1) / 2;
                            int c1 = 2 * x;

                            if (pair.Item1 < c1 && c1 < pair.Item2)
                            {
                                // To deduplicate: the possible sets of integer medians are:
                                //     m_c
                                //     m_a, m_c
                                //     m_b, m_c
                                //     m_a, m_b, m_c
                                // We only want to add if c is (wlog) the shortest edge whose median is integral (or joint integral in case of isosceles triangles).

                                if (c1 <= a) count++;
                                else if (!IsIntegerMedian(b, c1, a))
                                {
                                    if (c1 <= b || !IsIntegerMedian(a, c1, b)) count++;
                                }
                            }

                            int c2 = 2 * y;
                            if (c1 != c2 && c2 <= n && pair.Item1 < c2 && c2 < pair.Item2)
                            {
                                if (c2 <= a) count++;
                                else if (!IsIntegerMedian(b, c2, a))
                                {
                                    if (c2 <= b || !IsIntegerMedian(a, c2, b)) count++;
                                }
                            }
                        }
                    }
                }
            }

            return count;
        }

        private static bool IsIntegerMedian(int a, int b, int c)
        {
            int m2 = 2 * (a * a + b * b) - c * c;
            int s = (int)(0.5f + Math.Sqrt(m2));
            return ((s & 1) == 0) && (m2 == s * s);
        }
    }
}

n ถูกนำมาเป็นอาร์กิวเมนต์บรรทัดคำสั่ง

คำอธิบาย

ม.=(2a2+22-2)/42a2+22=4ม.2+22=2a2+2=2(ม.2+2)a2+2 จะต้องเป็นเช่นนั้น a และ จะต้องมีความเท่าเทียมกัน

สมการ a2+2=2(ม.2+2) เป็นพื้นฐานสำหรับอัลกอริทึม Meet-in-the-the-middle ที่นี่

ถ้า a และ แปลกแล้วเราไม่มีความเสี่ยงในการนับซ้ำเนื่องจากมีเพียงหนึ่งในสามค่ามัธยฐานเท่านั้นที่สามารถเป็นส่วนประกอบได้ หากทั้งสามคนเป็นคู่เราต้องระวังการนับซ้ำ ดังนั้นฉันจัดการกับทั้งสองกรณีแยกกันเพื่อให้สามารถประมวลผลกรณีคี่ - คู่ได้เร็วกว่าเคสคู่ - คู่ - คู่


ฉันไม่สามารถสร้าง Felix บนเครื่องของฉันได้ แต่เวลาของฉันn=5000คือ 67 วินาทีสำหรับคำตอบของ Reto Koradi 48 วินาทีสำหรับคำตอบของ Sp3000 และ 13 วินาทีสำหรับคำตอบของฉัน
Peter Taylor

0

C, n = 3030 ที่นี่

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define R     return
#define u32 unsigned
#define F        for
#define P     printf

int isq(u32 a)
{u32 y,x,t,i;
 static u32  arr720[]={0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400,441,484,529,576,625,676,180,241,304,369,436,505,649,160,409,496,585,340,544,145,601,244,580,481,640,385,265};
 static char barr[724]={0};
 if(barr[0]==0)F(i=0;i<(sizeof arr720)/sizeof(unsigned);++i)
                if(arr720[i]<720) barr[arr720[i]]=1; 
 if(barr[a%720]==0) R 0;
 y=sqrt(a);
 R y*y==a;
}

int f(u32 a, u32 b, u32 c)
{u32 t,x;
 if(c&1)R 0;
 t= a*a+b*b;
 if(t&1)R 0;
 R isq((2*t-c*c)/4);
}

int h(u32 n)
{u32 cnt,a,c,k,ke,kc,d,v,l,aa,bb,cc;

 cnt=0;
 F(a=1;a<=n;++a)
   {ke=(n-a)/2;
    F(k=0;k<=ke;++k)
        {v=a+k;
         d=v*v+k*k;
         l=sqrt(d);
         v=n/2;
         if(l>v)l=v;
         v=a+k-1;
         if(l>v)l=v;
         F(c=k+1;c<=l;++c)
           {if(isq(d-c*c))
                {bb=a+2*k;cc=2*c;
                 if(bb>cc && f(a, cc,bb)) continue;
                 if( a>cc && f(cc,bb, a)) continue;
                 ++cnt;
                 //P("|a=%u b=%u c=%u", a, bb, cc);
                }
           }
        }
   }
 R cnt; 
}

int main(int c, char** a)
{time_t  ti, tf;
 double   d;
 int     ni;
 u32    n,i;

 if(c!=2||a[1]==0){P("uso: questo_programma.exe  arg1\n ove arg1 e\' un numero positivo\n");R 0;}
 ni=atoi(a[1]);
 if(ni<=0){P("Parametro negativo o zero non permesso\n");R 0;}
 n=ni;
 if(n>0xFFFFF){P("Parametro troppo grande non permesso\n"); R 0;}
 F(i=3;i<33;++i)if(i<10||i>21)P("T(%u)=%u|",i, h(i));
 ti=time(0);
 P("\nT(%u)=%u\n", n, h(n));
 tf=time(0);
 d=difftime(tf,ti);
 P("Tempo trascorso = %.2f sec\n", d); 
 R 1;
}

ผล:

C:\Users\a\b>prog 3030
T(3)=0|T(4)=0|T(5)=0|T(6)=1|T(7)=1|T(8)=2|T(9)=3|T(22)=34|T(23)=37|T(24)=42|T(25)=
45|T(26)=56|T(27)=59|T(28)=65|T(29)=67|T(30)=74|T(31)=79|T(32)=91|
T(3030)=3321226
Tempo trascorso = 60.00 sec

รหัสข้างต้นจะเป็น traslation ใน C ของคำตอบที่แท้จริง (ถ้าเราไม่นับฟังก์ชั่น isq ())

คอมไพเลอร์ของฉันไม่เชื่อมโยงฟังก์ชั่นที่คนอื่นใช้ sqrtf () ... ที่นี่ไม่มีฟังก์ชัน sqrt สำหรับโฟลต ... พวกเขาแน่ใจหรือไม่ว่า sqrtf เป็นฟังก์ชั่นมาตรฐาน C?



0

APL NARS, n = 239 282 ใน 59 วินาที

f←{(a b c)←⍵⋄1=2∣c:0⋄t←+/a b*2⋄1=2∣t:0⋄0=1∣√4÷⍨(2×t)-c*2}

∇r←g n;cnt;c;a;k;kc;ke;d;l;bb;cc
    r←⍬⋄cnt←0
    :for a :in 1..n 
       ke←⌊(n-a)÷2
       :for k :in 0..ke
          d←((a+k)*2)+k*2
          kc←⌊⌊/(n÷2),(a+k-1),√d
          →B×⍳kc<k+1  
          :for c :in (k+1)..kc
            →C×⍳∼1e¯9>1∣√d-c*2
               bb←a+2×k⋄cc←2×c
               →C×⍳(bb>cc)∧f a  cc bb
               →C×⍳( a>cc)∧f cc bb  a
               cnt+←1
               ⍝r←r,⊂a bb cc
   C:     :endfor
   B:  :endfor
    :endfor
    r←r,cnt
∇

(i traslate the Axiom ตอบหนึ่งในการทดสอบ APL):

  g 282 
16712 
  v←5 6 10 20 30 41
  v,¨g¨v
5 0  6 1  10 4  20 27  30 74  41 166 

0

Axiom, n = 269 ใน 59 วินาที

isq?(x:PI):Boolean==perfectSquare?(x)

f(a:PI,b:PI,c:PI):Boolean==
    c rem 2=1=>false
    t:=a^2+b^2
    t rem 2=1=>false
    x:=(2*t-c^2)quo 4
    isq?(x)

h(n)==
   cnt:=0  -- a:=a   b:=(a+2*k)  c:=
   r:List List INT:=[]
   for a in 1..n repeat
     ke:=(n-a)quo 2
     for k in 0..ke repeat
         d:=(a+k)^2+k^2 -- (a^2+b^2)/2=(a+k)^2+k^2   m^2+c^2=d
         l:=reduce(min,[sqrt(d*1.), n/2.,a+k-1])
         kc:=floor(l)::INT
         for c in k+1..kc repeat
             if isq?(d-c^2) then
                            bb:=a+2*k; cc:=2*c
                            if bb>cc and f(a,cc,bb) then iterate   -- 2<->3
                            if  a>cc and f(cc,bb,a) then iterate   -- 1<->3
                            cnt:=cnt+1
                            --r:=cons([a,a+2*k,2*c],r)
   r:=cons([cnt],r)
   r

ถ้า a, b, cx คือความยาวด้านข้างของสามเหลี่ยมหนึ่งรูปของความยาวสูงสุด n ...

เราจะรู้ว่า m: = sqrt ((2 * (a ^ 2 + b ^ 2) -cx ^ 2) / 4)

(1) m^2=(2*(a^2+b^2)-cx^2)/4

ดังที่ Peter Taylor กล่าวไว้ 4 | (2 * (a ^ 2 + b ^ 2) -cx ^ 2) และเพราะ 2 | 2 * (a ^ 2 + b ^ 2) มากกว่า 2 | cx ^ 2 => cx = 2 * ค ดังนั้นจาก 1 จะเป็น

(2) m^2=(a^2+b^2)/2-c^2

a, และ b ต้องมีความเท่าเทียมกันดังนั้นเราจึงสามารถเขียน b ในฟังก์ชันของ a

(3) a:=a   b:=(a+2*k)

กว่าที่เรามี

(4)(a^2+b^2)/2=(a^2+(a+2*k)^2)/2=(a+k)^2+k^2

ดังนั้น (1) สามารถเขียนใหม่ดู (2) (3) (4) เป็น:

m^2+c^2=(a+k)^2 + k^2=d         a:=a  b:=(a+2*k)  cx:=2*c

ที่ไหน

a in 1..n  
k in 0..(n-a)/2  
c in k+1..min([sqrt(d*1.), n/2.,a+k-1])

ผล

(16) -> h 269
   (16)  [[14951]]
                                                  Type: List List Integer
        Time: 19.22 (IN) + 36.95 (EV) + 0.05 (OT) + 3.62 (GC) = 59.83 sec

0

VBA 15,000 ในสิบวินาที!

ฉันคาดหวังมากน้อยกว่าหลังจากโพสต์อื่น ๆ เหล่านี้ ใน Intel 7 ที่มี RAM 16 GB ฉันได้รับ 13-15,000 ในสิบวินาที สำหรับ Pentium ที่มี RAM 4 GB ฉันจะได้รับ 5-7,000 ในสิบวินาที รหัสด้านล่าง นี่คือผลล่าสุดของ Pentium

abci= 240, 234, 114, 7367, 147
abci= 240, 235, 125, 7368, 145
abci= 240, 236, 164, 7369, 164
abci= 240, 238, 182, 7370, 221
abci= 240, 239, 31, 7371, 121

มันเพิ่มขึ้นเป็นรูปสามเหลี่ยมโดยมีด้าน 240, 239, 31 และสื่อกลาง 121 จำนวนของสื่อคือ 7,371

Sub tria()
On Error Resume Next
Dim i As Long, a As Integer, b As Integer, c As Integer, ma As Double, mb As Double, mc As Double, ni As Long, mpr As Long
Dim dtime As Date
dtime = Now
Do While Now < DateAdd("s", 10, dtime)  '100 > DateDiff("ms", dtime, Now) '
    a = a + 1
   ' Debug.Assert a < 23
    b = 1: c = 1
    Do
        ma = 0
        If a < b + c And b < a + c And c < a + b Then
            ma = ((2 * b ^ 2 + 2 * c ^ 2 - a ^ 2) / 4) ^ 0.5
            If ma <> 0 Then ni = i + 1 * -1 * (0 = ma - Fix(ma))
                If ni > i Then
                If ma <> mpr Then
                i = ni
                mpr = ma
                    Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i & ", " & ma
                    GoTo NextTri  'TO AVOID DOUBLE COUNTING
                End If
            End If
       'End If

        mb = 0
        'If b < a + c Then
            mb = ((2 * a ^ 2 + 2 * c ^ 2 - b ^ 2) / 4) ^ 0.5
            If mb <> 0 Then ni = i + 1 * -1 * (0 = mb - Fix(mb))
            If ni > i Then
            If mb <> mpr Then
                i = ni
                mpr = mb
                Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i & ", " & mb
                GoTo NextTri  'TO AVOID DOUBLE COUNTING
            End If
            End If
        'End If

        mc = 0
        'IfThen
            mc = ((2 * b ^ 2 + 2 * a ^ 2 - c ^ 2) / 4) ^ 0.5
            If mc <> 0 Then ni = i + 1 * -1 * (0 = mc - Fix(mc))
            If ni > i Then
            If mc <> mpr Then
            i = ni
            mpr = mc
                Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i & ", " & mc
            End If
            End If
        End If
NextTri:
        Do While c <= b
            'c = c + 1
            ma = 0
            If a < b + c And b < a + c And c < a + b Then

                    ma = ((2 * b ^ 2 + 2 * c ^ 2 - a ^ 2) / 4) ^ 0.5
                    If ma <> 0 Then ni = i + 1 * -1 * (0 = ma - Fix(ma))
                            If ni > i Then
                    If ma <> mpr Then
                        mpr = ma
                i = ni
                    End If
                    Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i & ", " & ma
                    GoTo NextTri2  'TO AVOID DOUBLE COUNTING
                End If
            'End If

            mb = 0
            'If b < a + c Then
                mb = ((2 * a ^ 2 + 2 * c ^ 2 - b ^ 2) / 4) ^ 0.5
                If mb <> 0 Then ni = i + 1 * -1 * (0 = mb - Fix(mb))
                        If ni > i Then
                If mb <> mpr Then
                mpr = mb
                i = ni
                    Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i & ", " & mb
                    GoTo NextTri2  'TO AVOID DOUBLE COUNTING
                End If
                End If
            'End If

            mc = 0
            'If c < b + a Then
                    mc = ((2 * b ^ 2 + 2 * a ^ 2 - c ^ 2) / 4) ^ 0.5
                    If mc <> 0 Then ni = i + 1 * -1 * (0 = mc - Fix(mc))
                            If ni > i Then
                    If mc <> mpr Then
                    mpr = mc
                i = ni
                    Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i & ", " & mc
                    End If
                End If
            End If
       ' Debug.Print "abci= " & a & ", " & b & ", " & c & ", " & i
            c = c + 1
        Loop 'While c <= a
NextTri2:
        b = b + 1
        c = 1
    Loop While b <= a
Loop
Debug.Print i

End Sub

1
ยินดีต้อนรับสู่ PPCG!
Martin Ender
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.