まぁ，関数型ではやりにくい．

とりあえず，javaで．

```import java.util.Arrays;
public class P187{
public static void main(String[] args){
int n = 100000000,c=;
boolean[] prime = new boolean[n];
Arrays.fill(prime,true);
for(int i=2,m=(int)Math.sqrt(n);i<m;i++)
if(prime[i]) for(int j=i*i;j<n;j+=i) prime[j]=false; // sieve prime
for(int i=2;i<n;i++){
if(prime[i]) continue;
for(int j=2*i;j<n;j+=i)prime[j]=true; // sieve semiprime
c++;
}
System.out.println(c);
}
}
```

あまり，速くない．

2回目のふるいの効率が良くない．

```import java.util.Arrays;
public class P187_1{
public static void main(String[] args){
int n = 100000000, m=(int)Math.sqrt(n);
boolean[] prime = new boolean[n/2+1];
Arrays.fill(prime,true);
int[] pi = new int [n/2+1];
for(int i=2 ; i<n/2+1 ; i++)
if(prime[i]){
if(i<m) for(int j = i*i ; j < n/2+1 ; j+=i) prime[j] = false; // sieve prime
pi[i] = pi[i-1]+1;
}else pi[i] = pi[i-1];
int count = ;
for(int i=2 ;i <=m ;i++)
if(prime[i]) count+=pi[n/i]-pi[i]+1;
System.out.println(count);
}
}
```

```{-# LANGUAGE BangPatterns #-}
p187 n = do
q <- newArray (2,div n 2) True :: ST s (STUArray s Int Bool)
p <- newArray (1,div n 2)  :: ST s (STUArray s Int Int)
let m = floor.sqrt.fromIntegral \$ n
countP !i
| i > div n 2 = return ()
| otherwise = do
if q_i
then do when (i<m) \$ sieve i (i*i)
readArray p (i-1) >>= writeArray p i.(1+)
countP (i+1)
else do readArray p (i-1) >>= writeArray p i
countP (i+1)
sieve !i !j
| j > div n 2 = return ()
| otherwise = writeArray q j False >> sieve i (j+i)
semiPrime !c !i
| i > m = return c
| otherwise = do