|
规则不清楚,早知道就很好办了。
declare
f number;
begin
delete p;
insert into p(n)
WITH t AS (
SELECT 2*ROWNUM+1 n FROM DUAL CONNECT BY ROWNUM <= (:n)/2-1-1
)
SELECT n
FROM (SELECT n from t
MINUS
SELECT t1.n * t2.n
FROM t t1, t t2
WHERE t1.n <= t2.n
AND t1.n <= (SELECT SQRT(:n) FROM DUAL)
AND t1.n * t2.n <:n
)
union all select 2 from dual;
delete pairs;
insert into pairs(p1,p2)
with pair as (
select p1.n p1,p2.n p2
from p p1,p p2
where p1.n<p2.n
and (substr(p2.n,2)=to_char(p1.n)
or (length(p1.n)=length(p2.n)
and to_number(rtrim(p2.n-p1.n,'0')) between 1 and 9
and substr(p2.n,-length(p2.n-p1.n),1)
>substr(p1.n,-length(p2.n-p1.n),1)
)
)
)
select p1,p2 from pair union all select p2,p1 from pair
;
delete res;
insert into res (wm,n,path)
select 0,p2,p2 from pairs where p1=2;
LOOP
MERGE INTO res USING (
select r2.*
from (select pairs.p2 as n
,MIN(CASE WHEN pairs.p1<pairs.p2 THEN CASE WHEN res.wm<pairs.p2 THEN 0 ELSE res.wm END
WHEN pairs.p1>pairs.p2 THEN greatest(res.wm, pairs.p1)
END) wm
,min(res.path||','||pairs.p2) keep(dense_rank first order by
CASE WHEN pairs.p1<pairs.p2 THEN CASE WHEN res.wm<pairs.p2 THEN 0 ELSE res.wm END
WHEN pairs.p1>pairs.p2 THEN greatest(res.wm, pairs.p1)
END ) path
from res join pairs on res.n=pairs.p1
group by pairs.p2
) r2
left join res res2 on r2.n=res2.n
where res2.n is null
or res2.n is NOT null
AND r2.wm<res2.wm
) d
ON (d.n=res.n)
WHEN NOT MATCHED THEN INSERT (wm,n,path) values (d.wm,d.n,d.path)
WHEN MATCHED THEN UPDATE SET wm=d.wm,path=d.path;
EXIT WHEN SQL%ROWCOUNT=0;
END LOOP;
select sum(n) into f from res where wm>0 and n<>2;
dbms_output.put_line(f);
end;
/
78728
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.00 |
|