あなたの関数f
(おそらくもっとわかりやすい名前を選ぶべきです)は、インデックス以降m
、配列内の素数のいずれかで割り切れる数を超えない数を返すことを意図しているようです。factors
start
int f(int *factors, int start, int nf, int m) //nf=no. of factors, start=0, m=M
{
if(start == nf-1)
return (m / factors[start]);
return (m / factors[start]) + f(factors, (start + 1), nf, m)
- ((f(factors, (start + 1), nf, m)) / factors[start]);
}
明らかに、プライムが1つしかないp
場合、カウントはm / p
です。ここまでは順調ですね。さて、他の部分の考え方は、それを超えない数の数は、または後の素数の1つでm
割り切れるということです。p
count_multiples_of_p + count_multiples_of_other - count_multiples_of_p_and_other
これまでのところ正しいです。しかし、あなたの実装は
count_multiples_of_p_and_other = count_multiples_of_other / p
これは漸近的に正しいだけです。たとえば、3つの素数[2, 3, 5]
とm = 20
。
関数は
F([2,3,5], 20) = 20/2 + F([3,5], 20) - F([3,5], 20)/2
-- F([3,5], 20) = 20/3 + 20/5 - (20/5)/3 = 6 + 4 - 1 = 9
= 10 + 9 - (9/2) = 10 + 9 - 4 = 15
しかし、数えると<= 20
、3つの素数のいずれでも割り切れない6つの数が1, 7, 11, 13, 17, 19
あるため、3つのいずれかの倍数であるのは14だけです。
後の素数の倍数と後の素数のいずれかを説明する正しい方法は、後の素数の倍数であり、後の素数の少なくとも1つである場合、は倍数であるため、p
を超えない後の素数の倍数を数えることです。を超えない後の素数の1つの。m/p
k
p
k/p
m/p
したがって、関数の修正は、括弧を移動するだけで構成されます(まあ、2つあるので、たくさんあります)。
int f(int *factors, int start, int nf, int m) //nf=no. of factors, start=0, m=M
{
if(start == nf-1)
return (m / factors[start]);
return (m / factors[start]) + f(factors, (start + 1), nf, m)
- ((f(factors, (start + 1), nf, m /* )) */ / factors[start]) ));
// ^^^^^^^^ ^^
}
(そして、いくつかの余分な括弧のペアがある場合は、それらのいくつかを削除することを検討してください)。