I ran the perf test and these were the results compared to s1 and s2.
Below 1000:
f n total average mem
---------------------------------------------------------------------
(`s1;1000;3 5) 100000 0D00:00:01.000680000 0D00:00:00.000010007 41120
(`s2;999;3 5) 100000 0D00:00:00.061489000 0D00:00:00.000000615 384
(`lfox;1000) 100000 0D00:00:00.261888000 0D00:00:00.000002619 17536
Below 100000:
f n total average mem
-----------------------------------------------------------------------
(`s1;100000;3 5) 1000 0D00:00:01.112241000 0D00:00:00.001112241 5243040
(`s2;99999;3 5) 1000 0D00:00:00.000624000 0D00:00:00.000000624 384
(`lfox;100000) 1000 0D00:00:00.149855000 0D00:00:00.000149855 1310848
Yeah, it still has to create and traverse the list of numbers, so space and time requirements will grow with n. But, it is a significant improvement over s1!
Interesting solution to build up the multiples using the take (#) on the Boolean list to create a repeated list with the true values occurring where the multiples lay.