Hello, there was interesting simple math problem I have recently solved :
- How many positive integers in a range 1 to n are divisible by at least one of given primes ?
Here is the recursive function that solves the problem :
- // n range of numbers from 1 to n
- // p array of primes for divisibility check
- long f(long n, long [] p)
- {
- if(p.Length==0)
- return 0;
- long [] q = new long[p.Length-1];
- Array.Copy(p,1,q,0,p.Length-1);
- long r = (n/p[0])- (f(n/p[0],q)) + (f(n,q));
- return r;
- }
My question is :
- Is it possible to write this function in C# differently so that its execution becomes faster ?
All the best,
Željko Peric

Arun PottiPosted Nov 1, 2026, 1:23 AM
Your recursion is essentially applying the inclusion-exclusion principle, but it creates a new array with
Array.Copyon every recursive call and repeats calculations. You can make it faster by iterating over combinations of the primes and avoiding array allocations.static long Count(long n, long[] primes)
{
long result = 0;
int combinations = 1 << primes.Length;
for (int mask = 1; mask < combinations; mask++)
{
long product = 1;
int count = 0;
bool valid = true;
for (int i = 0; i < primes.Length; i++)
{
if ((mask & (1 << i)) == 0)
continue;
// Avoid overflow and combinations that cannot divide
// any number <= n.
if (product > n / primes[i])
{
valid = false;
break;
}
product *= primes[i];
count++;
}
if (!valid)
continue;
long divisible = n / product;
if ((count & 1) == 1)
result += divisible;
else
result -= divisible;
}
return result;
}
Željko PerićPosted Oct 31, 2026, 9:28 PM
For everyone who wants to download the complete source code, explore advanced optimizations (including
CollectionsMarshalandInt128versions), the project is available at the following link:periczeljkosmederevo/CountDivisibleNumbers
High-performance C# implementation and benchmarks for counting numbers in a range divisible by given primes using the Inclusion-Exclusion Principle.
Željko PerićPosted Oct 31, 2026, 9:06 PM
New examples of more optimized code:
Benchmark Environment & System Specs:
BenchmarkDotNet Version: v0.15.8
Operating System: Windows 11 (10.0.26300.9818)
Processor (CPU): 13th Gen Intel Core i7-1360P 2.20GHz, 1 CPU, 16 logical and 12 physical cores
SDK / Runtime: .NET SDK 10.0.403 (RyuJIT x86-64-v3)
All the best,
Željko Perić
Željko PerićPosted Oct 31, 2026, 8:29 PM
After 8 years here is improved version of upper solution that gives currently best performance speed/memory:
Benchmark Environment & System Specs:
BenchmarkDotNet Version: v0.15.8
Operating System: Windows 11 (10.0.26300.9711)
Processor (CPU): 13th Gen Intel Core i7-1360P 2.20GHz, 1 CPU, 16 logical and 12 physical cores
SDK / Runtime: .NET SDK 10.0.403 (RyuJIT x86-64-v3)
Conclusion:
The evolution from a naive linear scan to an advanced recursive algorithm based on the Inclusion-Exclusion Principle demonstrates how number theory combined with modern .NET optimization techniques (such as dictionary-based memoization) can solve complex computational tasks within microseconds. Benchmark results clearly confirm that the memoized version incurs zero managed memory allocations (0 B) and vastly outperforms the original recursion, ensuring robust, lightning-fast performance even with colossal ranges up to
long.MaxValue.All the best,
Željko Peric
Dharmraj ThakurPosted Jan 3, 2018, 7:30 AM
Željko PerićPosted Jan 3, 2018, 7:14 AM
Dharmraj ThakurPosted Jan 1, 2018, 2:01 AM