grisРеализация идеи
wrest с дополнительными оптимизациями:
Код:
? M=1000; N=0; for(i=1,M, for(j=i,M, for(k=j,M, if(gcd([i,j,k])==1, N++;); ))); print(floor(100*N/(M*(M+1)*(M+2)/6)))\\Ваш исходный вариант
83
time = 1min, 18,266 ms.
? M=1000; N=0; for(i=1,M, for(j=i,M, t=gcd(i,j); if(t==1, N+=M-j+1, for(k=j,M, if(gcd(t,k)==1, N++;);); ))); print(floor(100*N/(M*(M+1)*(M+2)/6)))\\Добавим ему оптимизации
83
time = 17,364 ms.
? M=2000; N=0; for(i=1,M, for(j=i,M, t=gcd(i,j); if(t==1, N+=M-j+1, for(k=j,M, if(gcd(t,k)==1, N++;);); ))); print(floor(100*N/(M*(M+1)*(M+2)/6)))\\Увеличим предел вдвое
83
time = 2min, 21,540 ms.
? M=1000; b=vector(M); for(x=2,M, t=0; foreach(factor(x)[,1],p, t=bitor(t,2^p)); b[x]=t;);\\Формирование факторизаций, единицы мс
? N=0; for(i=1,M, for(j=i,M, t=bitand(b[i],b[j]); for(k=j,M, if(bitand(t,b[k])==0, N++;); ))); print(floor(100*N/(M*(M+1)*(M+2)/6)))\\Используем
83
time = 45,959 ms.
? M=1000; b=vector(M); for(x=2,M, t=0; foreach(factor(x)[,1],p, t=bitor(t,2^p)); b[x]=t;);\\Формирование факторизаций, единицы мс
? N=0; for(i=1,M, for(j=i,M, t=bitand(b[i],b[j]); if(t==0, N+=M-j+1, for(k=j,M, if(bitand(t,b[k])==0, N++;);); ))); print(floor(100*N/(M*(M+1)*(M+2)/6)))\\С оптимизацией лишнего цикла
83
time = 14,572 ms.
? M=2000; b=vector(M); for(x=2,M, t=0; foreach(factor(x)[,1],p, t=bitor(t,2^p)); b[x]=t;);\\Формирование факторизаций, единицы мс
? N=0; for(i=1,M, for(j=i,M, t=bitand(b[i],b[j]); if(t==0, N+=M-j+1, for(k=j,M, if(bitand(t,b[k])==0, N++;);); ))); print(floor(100*N/(M*(M+1)*(M+2)/6)))\\Увеличим предел вдвое
83
time = 2min, 5,254 ms.
Выходит смысла в предрасчёте факторизаций в общем и нет, достаточно не делать лишних циклов.
Рост времени от M практически кубический, как и ожидалось (три вложенных цикла). Значит до миллиона не досчитаете, даже до сотни тысяч. И дело не только в медленности gcd или bitand, а в кубической зависимости.
-- 29.10.2022, 20:11 --grisС другой стороны, значения N для каждого M уже посчитаны в
A015631.
Там и программы на PARI приведены,
намного быстрее:
Код:
? M=1000000; N=sum(k=1, M, sumdiv(k, d, moebius(k/d)*binomial(d+1, 2))); print("N=",N);print(floor(100*N/(M*(M+1)*(M+2)/6)));
N=138651542411519020
83
time = 5,836 ms.
Почему работает правильно — меня не спрашивайте.
-- 29.10.2022, 20:13 --Т.е. в таких случаях полезно найти самому несколько первых (или близких к началу) значений самой простой функции из требуемых — и поискать их в OEIS.