Project Euler 91:Right triangles with integer coordinates 格点直角三角形

Right triangles with integer coordinates

The points P (x1, y1) and Q (x2, y2) are plotted at integer co-ordinates and are joined to the origin, O(0,0), to form ΔOPQ.

There are exactly fourteen triangles containing a right angle that can be formed when each co-ordinate lies between 0 and 2 inclusive; that is,0 ≤ x1, y1, x2, y2 ≤ 2.

Given that 0 ≤ x1, y1, x2, y2 ≤ 50, how many right triangles can be formed?



格点直角三角形

点P(x1, y1)和点Q(x2, y2)都是格点,并与原点O(0,0)构成ΔOPQ。

当点P和点Q的所有坐标都在0到2之间,也就是说0 ≤ x1, y1, x2, y2 ≤ 2时,恰好能构造出14个直角三角形。

如果0 ≤ x1, y1, x2, y2 ≤ 50,能构造出多少个直角三角形?

 解题

先网上找到的答案,然后看题解中,前面几题给出了暴露的方法,遍历所有的点 ,判断是否是直角三角形就好了,最后的结果要除以2,,因为两个点是可以互换的。

Java

package Level3;

public class PE091{
    static void run(){
        int N = 50;
        int count = 0;
        // 第一个顶点
        for(int x1 = 0; x1<=N;x1++){
            for(int y1 = 0;y1<=N ;y1++){
                if(x1==0 && y1==0) continue;
                // 第二个顶点
                for(int x2 = 0;x2<=N;x2++){
                    for(int y2=0;y2<=N;y2++){
                        if(x2==0&&y2==0 || x1==x2&&y1==y2)
                            continue;
                        //判断是否是三角形
                        double d1 = getDistance(0,0,x1,y1);
                        double d2 = getDistance(0,0,x2,y2);
                        double d3 = getDistance(x1,y1,x2,y2);
                        if(d1+d2==d3|| d1+d3==d2||d2+d3==d1)
                            count++;
                    }
                }
            }
        }
        System.out.println(count/2);
    }
//    14234
//    running time=0s71ms
    static double getDistance(int x1,int y1,int x2,int y2){
        double d1 = (x1-x2)*(x1-x2);
        double d2 = (y1-y2)*(y1-y2);
        return d1+d2;
    }

    public static void main(String[] args) {
        long t0 = System.currentTimeMillis();
        run();
        long t1 = System.currentTimeMillis();
        long t = t1 - t0;
        System.out.println("running time="+t/1000+"s"+t%1000+"ms");

    }
}

参考链接1  参考链接2

上面给出来很好的不用暴力的方法

对于直角在原点的情况:

P Q两点只能在x轴  y轴上,固定一点看另一点,显然有50中可能,然而这一点也有50种可能,共2500种

对于直角在x轴或者y轴的情况:

当P 在x轴上的某点时候,Q的x坐标显然要和P 的一样,PQ都各有50个位置,共2500种

当P 在y轴的时候,也有2500种

对于直角在方格内部的时候:

要使得是直角三角形:OP要垂直PQ

OP的斜率:k = dy/dx  (dy/dx是最简分数)    其中P的坐标设为(x,y)

则PQ的斜率是:-dx/dy

如何根据斜率,找到Q的整数点,或者Q点的个数。

当P点的y轴值>Q点的y轴的值时候:

(如上图所示)可以发现:Q1 Q2 把PQ3等分成三份。三个Q点都是整数点。

对斜率为k = dy/dx :可以通过一个dy * dx的方格表示出来,所以,对于P(x,y)点,x每加一个dx y每减一个dy都是一个整数Q点,那么有多少个符合要求的点?只需要看最大能走多少步,

对于PQ的斜率是dx/dy,当P(x,y),   对x而言最大的步数是:(N-x)/dy ,对y而言最大的步数是:y/dx

这样其最小值就是Q的整数点数:MIN((N-x)/dy,y/dx)

当P点的y轴值<Q点的y轴的值时候:


PQ的斜率是:-dx/dy

P(x,y) x向左走的最大步数:x/dy y向上走的最大步数:(N-y)/dx

这样其最小值就是Q的整数点数:MIN(x/dy,(N-y)/dx)

这与上面链接的结果不一样,根据运行结果发现答案是一样的

其实吧 对于P点的坐标可以是在N*N方格中的任意一点,P的坐标是可以对称的,所以可以直接乘以二的。

JAVA

package Level3;

public class PE091{
    static void run1(){
        int N = 50;
        // 直角在原点,直角在x轴 直角在y轴,个数都是N*N
        int result =N*N*3;
        //下面只需要对直角在方格内部的情况
        for(int x = 1;x<= N;x++){
            for(int y=1;y<= N;y++){
                int fact = gcd(x,y);
                result += Math.min(y*fact/x, (N-x)*fact/y);
                result += Math.min(x*fact/y, (N-y)*fact/x);
            }
        }
        System.out.println(result);
    }
//    14234
//    running time=0s78ms
    static int gcd(int x,int y){
        if(x<y){
            int tmp = x;
            x = y;
            y = tmp;
        }
        int r = x%y;
        while(r!=0){
            int tmp =x;
            x = y;
            y = tmp%x;
            r = x%y;
        }
        return y;
    }
    static void run(){
        int N = 50;
        int count = 0;
        // 第一个顶点
        for(int x1 = 0; x1<=N;x1++){
            for(int y1 = 0;y1<=N ;y1++){
                if(x1==0 && y1==0) continue;
                // 第二个顶点
                for(int x2 = 0;x2<=N;x2++){
                    for(int y2=0;y2<=N;y2++){
                        if(x2==0&&y2==0 || x1==x2&&y1==y2)
                            continue;
                        //判断是否是三角形
                        double d1 = getDistance(0,0,x1,y1);
                        double d2 = getDistance(0,0,x2,y2);
                        double d3 = getDistance(x1,y1,x2,y2);
                        if(d1+d2==d3|| d1+d3==d2||d2+d3==d1)
                            count++;
                    }
                }
            }
        }
        System.out.println(count/2);
    }
//    14234
//    running time=0s71ms
    static double getDistance(int x1,int y1,int x2,int y2){
        double d1 = (x1-x2)*(x1-x2);
        double d2 = (y1-y2)*(y1-y2);
        return d1+d2;
    }

    public static void main(String[] args) {
        long t0 = System.currentTimeMillis();
        run();
        long t1 = System.currentTimeMillis();
        long t = t1 - t0;
        System.out.println("running time="+t/1000+"s"+t%1000+"ms");

    }
}

Python

# coding=gbk

import time as time
from itertools import combinations
def run():
    N = 50
    count  = N*N*3
    for x in range(1,N+1):
        for y in range(1,N+1):
            fact = gcd(x,y)
            count += min((N-x)*fact/y,y*fact/x)*2
    print count 

# 14234
# running time= 0.00300002098083 s
def gcd(x,y):
    if x<y:
        x,y = y,x
    while x%y!=0:
        tmp = x
        x = y
        y = tmp%y
    return y 

t0 = time.time()
run()
t1 = time.time()
print "running time=",(t1-t0),"s"
时间: 2024-10-05 23:50:07

Project Euler 91:Right triangles with integer coordinates 格点直角三角形的相关文章

Project Euler:Problem 91 Right triangles with integer coordinates

The points P (x1, y1) and Q (x2, y2) are plotted at integer co-ordinates and are joined to the origin, O(0,0), to form ΔOPQ. There are exactly fourteen triangles containing a right angle that can be formed when each co-ordinate lies between 0 and 2 i

Python练习题 048:Project Euler 021:10000以内所有亲和数之和

本题来自 Project Euler 第21题:https://projecteuler.net/problem=21 ''' Project Euler: Problem 21: Amicable numbers Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). If d(a) = b and d(b) = a, where a ≠ b

Python练习题 047:Project Euler 020:阶乘结果各数字之和

本题来自 Project Euler 第20题:https://projecteuler.net/problem=20 ''' Project Euler: Problem 20: Factorial digit sum n! means n × (n ? 1) × ... × 3 × 2 × 1 For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, and the sum of the digits in the number 10! i

Python练习题 046:Project Euler 019:每月1日是星期天

本题来自 Project Euler 第19题:https://projecteuler.net/problem=19 ''' How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? Answer: 171 ''' from datetime import * firstDay = date(1901,1,1) lastDay = date(

Python练习题 035:Project Euler 007:第10001个素数

本题来自 Project Euler 第7题:https://projecteuler.net/problem=7 # Project Euler: Problem 7: 10001st prime # By listing the first six prime numbers: # 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. # What is the 10 001st prime number? # Answer

Python练习题 034:Project Euler 006:和平方与平方和之差

本题来自 Project Euler 第6题:https://projecteuler.net/problem=6 # Project Euler: Problem 6: Sum square difference # The sum of the squares of the first ten natural numbers is, # 1**2 + 2**2 + ... + 10**2 = 385 # The square of the sum of the first ten natur

Project Euler 126 - Cuboid layers

这题先是推公式- 狂用不完全归纳+二次回归,最后推出这么一个奇怪的公式 f(t,x,y,z)=4(t?1)(x+y+z+t?2)+2(xy+yz+xz) 表示长宽高为x .y .z 的立方体第t 层放的立方体的个数. 接下来就是算答案了- 方法很简单:暴力 但是暴力还是有技巧的,开始我是直接从1到1000枚举t .x .y .z ,但这样出不来结果. 换成下面代码里的方法就行了. 1 #include <iostream> 2 #include <cstdio> 3 #includ

Project Euler 第一题效率分析

Project Euler: 欧拉计划是一系列挑战数学或者计算机编程问题,解决这些问题需要的不仅仅是数学功底. 启动这一项目的目的在于,为乐于探索的人提供一个钻研其他领域并且学习新知识的平台,将这一平台打造一个有趣和休闲 的环境. 项目主页:https://projecteuler.net 第一题 Multiples of 3 and 5 If we list all the natural numbers below 10 that are multiples of 3 or 5, we ge

Python练习题 042:Project Euler 014:最长的考拉兹序列

本题来自 Project Euler 第14题:https://projecteuler.net/problem=14 ''' Project Euler: Problem 14: Longest Collatz sequence The following iterative sequence is defined for the set of positive integers: n → n/2 (n is even) n → 3n + 1 (n is odd) Using the rule