|
|
SQL虽然写出来了,但是效率不高,1000以上就很慢了,因为消除公因子的算法太差。
WITH n AS (SELECT LEVEL N FROM DUAL WHERE MOD(SQRT(LEVEL),1)>0 CONNECT BY LEVEL<=50)
,t(A,B,C,D,STR,GCD,N) AS (
SELECT TRUNC(SQRT(N)),1,TRUNC(SQRT(N)),1,CAST('~' AS VARCHAR2(4000)),100000,N FROM n
UNION ALL
SELECT CASE WHEN GCD>LEAST(B,C,D) THEN TRUNC((D*B*SQRT(N)+D*B*C)/(B*B*N - C*C)) ELSE A END
,CASE WHEN GCD>LEAST(B,C,D) THEN D*B
WHEN MOD(B,GCD)=0 AND MOD(C,GCD)=0 AND MOD(D,GCD)=0 THEN B/GCD
ELSE B
END
,CASE WHEN GCD>LEAST(B,C,D) THEN TRUNC((D*B*SQRT(N)+D*B*C)/(B*B*N - C*C))*(B*B*N - C*C) - D*C
WHEN MOD(B,GCD)=0 AND MOD(C,GCD)=0 AND MOD(D,GCD)=0 THEN C/GCD
ELSE C
END
,CASE WHEN GCD>LEAST(B,C,D) THEN B*B*N - C*C
WHEN MOD(B,GCD)=0 AND MOD(C,GCD)=0 AND MOD(D,GCD)=0 THEN D/GCD
ELSE D
END
,CASE WHEN GCD>LEAST(B,C,D) THEN STR||A||','||B||','||C||','||D||'~' ELSE STR END
,CASE WHEN GCD>LEAST(B,C,D) OR MOD(B,GCD)=0 AND MOD(C,GCD)=0 AND MOD(D,GCD)=0 THEN 2 ELSE GCD+1 END
,N
FROM t
WHERE INSTR(STR,'~'||A||','||B||','||C||','||D||'~')=0
) CYCLE A,B,C,D,GCD,N SET cycle_flag TO 'Y' DEFAULT 'N'
SELECT n,LENGTH(STR)-LENGTH(REPLACE(STR,'~')) p
FROM (SELECT N,SUBSTR(STR, INSTR(STR,'~'||A||','||B||','||C||','||D||'~')+1) AS STR
FROM T
WHERE INSTR(STR,'~'||A||','||B||','||C||','||D||'~')>0
)
ORDER BY 1
; |
|