记C为半径为r的圆,其方程为x2 + y2 = r2。我们选取两个点P(a, b)和Q(-a, c),使得过PQ的直线与圆C相切。

例如,四元组(r, a, b, c) = (2, 6, 2, -7)就满足上述性质。

记F(R, X)是满足上述性质的整数四元组(r, a, b, c)的数目,要求0 < r ≤ R且0 < a ≤ X。

可以验证F(1, 5) = 10, F(2, 10) = 52以及F(10, 100) = 3384。
求F(108, 109) + F(109, 108)。

plot2d ([sqrt(4-x^2),-sqrt(4-x^2),[discrete, [6,-6], [2,-7]]],[x,-8,8],[y,-8,8],[legend,false],grid2d,same_xy);

p410
查看下图。显然,直线 y=r,y=-r,x=r,x=r都与圆相切 根据三角形全等,得到以下方程(r+a)^2+(r+b)^2=(a+b)^2,化简得r^2+r(a+b)r-ab=0 如果A(a,r),B(-r,-b)满足方程,则直线AB与圆相切,在此直线上的x=-a的点为要求的另一个点Q。A则为P。 要使r为整数,则d=(a+b)^2+4ab是完全平方数,如图a=6,b=4,则d=196。
p410a
用sql来查找上述方程的a,b(不是题目四元组的a,b)

with t as(select level l from dual connect by level<=5)
select a.l a ,b.l b from t a,t b
where (-(a.l+b.l)+sqrt((a.l+b.l)*(a.l+b.l)+a.l*b.l*4))/2=1
;
         A          B
---------- ----------
         2          3
         3          2

with t as(select level l from dual connect by level<=10)
select a.l a ,b.l b from t a,t b
where (-(a.l+b.l)+sqrt((a.l+b.l)*(a.l+b.l)+a.l*b.l*4))/2=2
;
         A          B
---------- ----------
         3         10
         4          6
         6          4
        10          3

with t as(select level l from dual connect by level<=100),
r as(select level l from dual connect by level<=10)
select a.l a ,b.l b ,r.l r from t a,t b,r
where (-(a.l+b.l)+sqrt((a.l+b.l)*(a.l+b.l)+a.l*b.l*4))/2 =r.l 
;
         A          B          R
---------- ---------- ----------
         2          3          1
         3          2          1
         3         10          2
         4          6          2
         4         21          3
         5         12          3
         5         36          4
         6          4          2
         6          9          3
         6         20          4
         6         55          5
         7         30          5

已选择62行。

当F(1,5)时。所有的点都在2条水平直线上,分别是(x,1)(-x,1)(1<=x<=5)以及(x,-1)(-x,-1)(1<=x<=5) ,有10个四元组。虽然有一条斜线满足切线要求,但上面的点都不满足,因为(3+4t,1+3t)的正数x都是4n+3的形式,负数都是-4n-1的形式,不可能满足一个点x,另一个点-x。
当F(2,10)时。r=1时所有的点都在2条水平直线上,分别是(x,1)(-x,1)(1<=x<=10)以及(x,-1)(-x,-1)(1<=x<=10) ,有20个四元组。
r=2时,水平线上仍然有20个四元组。此外还有其他斜线上的点,以下SQL给出图示方向的3个四元组,加上向上平移,再加上关于y轴镜像,所以有3*4=12个四元组。

with t as(select level l from dual connect by level<=10), --X
r as(select level l from dual connect by level<=2), --R
v as(select level v from dual connect by level<=10), --divisor
ab as(select a.l a ,b.l b ,r.l r,a.l+r.l c,b.l+r.l k from t a,t b,r
where (-(a.l+b.l)+sqrt((a.l+b.l)*(a.l+b.l)+a.l*b.l*4))/2 =r.l),
d as(select a,b,c,k,r,max(v)maxv from v,ab where mod(c,v)=0 and mod(k,v)=0
group by a,b,c,r,k),
re as(
select d.a,d.b,d.r,l, (d.a+(l-5)*d.c/maxv) x,(d.r+(l-5)*d.k/maxv) y --l times
from t,ab,d
where
ab.a=d.a and ab.b=d.b
)
select  z.r,z.x,z.y,f.x,f.y from re z,re f
where z.a=f.a and z.b=f.b and z.r=f.r and z.x= -f.x and z.x>0 and z.x<=10;

    R          X          Y          X          Y
----- ---------- ---------- ---------- ----------
    2         10          5        -10        -10
    2          6          2         -6         -7
    2          2         -1         -2         -4

下面把F(10,100)的斜线分布输出

select r,(y-y1)/(x-x1)k,min(x),count(*) from p410 group by  r,(y-y1)/(x-x1) order by 1,2;

    R          K     MIN(X)   COUNT(*)
----- ---------- ---------- ----------
    2        .75          2         25  (3,4)
    3 1.33333333          3         33  (4,3)
    4        .75          4         25  (3,4)
    6 .416666667          6          8  (5,12)
    6        .75          2         25  (3,4)
    6 1.33333333          3         33  (4,3)
    8        .75          4         25  (3,4)
    9 1.33333333          3         33  (4,3)
   10        .75          2         25  (3,4)
   10        2.4          5         20  (12,5)

再把F(26,200)的斜线分布输出

select r,(y-y1)/(x-x1)k,min(x),count(*) from p410_3 group by  r,(y-y1)/(x-x1) order by 1,2;

    R          K     MIN(X)   COUNT(*)
----- ---------- ---------- ----------
    2        .75          2         50
    3 1.33333333          3         66
    4        .75          4         50
    6 .416666667          6         17
    6        .75          2         50
    6 1.33333333          3         66
    8        .75          4         50
    9 1.33333333          3         66
   10        .75          2         50
   10        2.4          5         40
   12 .291666667         12          8  (7,24,25)
   12 .416666667         12         16
   12        .75          4         50
   12 1.33333333          3         66
   12      1.875          4         25  (15,8,17)
   14        .75          2         50
   15 .533333333         15         13
   15 1.33333333          3         66
   16        .75          4         50
   18 .416666667          6         17
   18        .75          2         50
   18 1.33333333          3         66
   20       .225         20          5  (9,40,41)
   20        .75          4         50
   20        2.4          5         40
   21 1.33333333          3         66
   21 3.42857143          7         28  (24,7)
   22        .75          2         50
   24 .291666667         24          8
   24 .416666667         12         16
   24        .75          4         50
   24 1.33333333          3         66
   24      1.875          8         25
   26        .75          2         50

大致是这个规律:
1.与半径r的圆相切的斜线平行线与r的倍数的圆也相切,这些平行线的斜率相等,截距取决于原始勾股数,从而可能是题目要求的四元组,也可能不符合要求。比如r=2,只有斜率3/4符合,4/3就不符合。
2.随着r的变大,适合的原始勾股数也变多。比如r=6,除了(3,4),还多出了(5,12),r=12,又多出了(8,15)和(7,24).
3.一旦得到最小适合四元组的x和x方向的步长dx,就可以用公式X/dx算出四元组个数

SQL> select * from p410 where r=2;

         R          X          Y         X1         Y1
---------- ---------- ---------- ---------- ----------
         2          2         -1         -2         -4  --x方向步长4
         2          6          2         -6         -7
         2         10          5        -10        -10
         2         14          8        -14        -13
         2         18         11        -18        -16
...
已选择25行。