First triangular number whose number of divisors exceeds N
Last Updated :
29 Jul, 2022
Given a number N, find the first triangular number whose number of divisors exceeds N. Triangular numbers are sums of natural numbers, i. e., of the form x*(x+1)/2. First few triangular numbers are 1, 3, 6, 10, 15, 21, 28, …
Examples:
Input: N = 2
Output: 6
6 is the first triangular number with more than 2 factors.
Input: N = 4
Output: 28
A naive solution is to iterate for every triangular number and count the number of divisors using the Sieve method. At any moment if the number of divisors exceeds the given number N, then we get our answer. If the triangular number which has more than N divisors is X, then the time complexity will be O(X * sqrt(X)) as pre-processing of primes is not possible in case of larger triangular numbers. The naive solution is important to understand in order to solve the problem more efficiently.
An efficient solution will be to use the fact that the triangular number’s formula is x*(x+1)/2. The property that we will use is that k and k+1 are coprimes. We know that two co-primes have a distinct set of prime factors. There will be two cases when X is even and odd.
- When X is even, then X/2 and (X+1) will be considered as two numbers whose prime factorisation is to be find out.
- When X is odd, then X and (X+1)/2 will be considered as two numbers whose prime factorisation is to be find out.
Hence the problem has been reduced to the just finding out prime factorization of smaller numbers, which reduces the time complexity significantly. We can reuse the prime factorization for x+1 in the subsequent iterations, and thus factorizing one number in each iteration will do. Iterating till the number of divisors exceeds N and considering the case of even and odd will give us the answer.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX = 100000;
bool prime[MAX + 1];
void sieve()
{
memset (prime, true , sizeof (prime));
for ( int p = 2; p * p < MAX; p++)
if (prime[p] == true )
for ( int i = p * 2; i < MAX; i += p)
prime[i] = false ;
}
int divCount( int n)
{
int total = 1;
for ( int p = 2; p <= n; p++) {
if (prime[p]) {
int count = 0;
if (n % p == 0) {
while (n % p == 0) {
n = n / p;
count++;
}
total = total * (count + 1);
}
}
}
return total;
}
int findNumber( int n)
{
if (n == 1)
return 3;
int i = 2;
int count = 0;
int second = 1;
int first = 1;
while (count <= n) {
if (i % 2 == 0) {
first = divCount(i + 1);
count = first * second;
}
else {
second = divCount((i + 1) / 2);
count = first * second;
}
i++;
}
return i * (i - 1) / 2;
}
int main()
{
int n = 4;
sieve();
cout << findNumber(n);
return 0;
}
|
Java
public class GFG {
final static int MAX = 100000 ;
static boolean prime[] = new boolean [MAX + 1 ];
static void sieve()
{
for ( int i = 0 ; i <= MAX ; i++)
prime[i] = true ;
for ( int p = 2 ; p * p < MAX; p++)
if (prime[p] == true )
for ( int i = p * 2 ; i < MAX; i += p)
prime[i] = false ;
}
static int divCount( int n)
{
int total = 1 ;
for ( int p = 2 ; p <= n; p++) {
if (prime[p]) {
int count = 0 ;
if (n % p == 0 ) {
while (n % p == 0 ) {
n = n / p;
count++;
}
total = total * (count + 1 );
}
}
}
return total;
}
static int findNumber( int n)
{
if (n == 1 )
return 3 ;
int i = 2 ;
int count = 0 ;
int second = 1 ;
int first = 1 ;
while (count <= n) {
if (i % 2 == 0 ) {
first = divCount(i + 1 );
count = first * second;
}
else {
second = divCount((i + 1 ) / 2 );
count = first * second;
}
i++;
}
return i * (i - 1 ) / 2 ;
}
public static void main(String args[])
{
int n = 4 ;
sieve();
System.out.println(findNumber(n));
}
}
|
Python3
from math import sqrt
MAX = 100000
prime = [ True for i in range ( MAX + 1 )]
def sieve():
k = int (sqrt( MAX ))
for p in range ( 2 ,k, 1 ):
if (prime[p] = = True ):
for i in range (p * 2 , MAX ,p):
prime[i] = False
def divCount(n):
total = 1
for p in range ( 2 ,n + 1 , 1 ):
if (prime[p]):
count = 0
if (n % p = = 0 ):
while (n % p = = 0 ):
n = n / p
count + = 1
total = total * (count + 1 )
return total
def findNumber(n):
if (n = = 1 ):
return 3
i = 2
count = 0
second = 1
first = 1
while (count < = n):
if (i % 2 = = 0 ):
first = divCount(i + 1 )
count = first * second
else :
second = divCount( int ((i + 1 ) / 2 ))
count = first * second
i + = 1
return i * (i - 1 ) / 2
if __name__ = = '__main__' :
n = 4
sieve()
print ( int (findNumber(n)))
|
C#
using System;
public class GFG {
static int MAX = 100000;
static bool [] prime = new bool [MAX + 1];
static void sieve()
{
for ( int i = 0 ; i <= MAX ; i++)
prime[i] = true ;
for ( int p = 2; p * p < MAX; p++)
if (prime[p] == true )
for ( int i = p * 2; i < MAX; i += p)
prime[i] = false ;
}
static int divCount( int n)
{
int total = 1;
for ( int p = 2; p <= n; p++) {
if (prime[p]) {
int count = 0;
if (n % p == 0) {
while (n % p == 0) {
n = n / p;
count++;
}
total = total * (count + 1);
}
}
}
return total;
}
static int findNumber( int n)
{
if (n == 1)
return 3;
int i = 2;
int count = 0;
int second = 1;
int first = 1;
while (count <= n) {
if (i % 2 == 0) {
first = divCount(i + 1);
count = first * second;
}
else {
second = divCount((i + 1) / 2);
count = first * second;
}
i++;
}
return i * (i - 1) / 2;
}
public static void Main()
{
int n = 4;
sieve();
Console.Write(findNumber(n));
}
}
|
PHP
<?php
$MAX = 10000;
$prime = array_fill (0, $MAX + 1, true);
function sieve()
{
global $prime ;
global $MAX ;
for ( $p = 2; $p * $p < $MAX ; $p ++)
if ( $prime [ $p ] == true)
for ( $i = $p * 2;
$i < $MAX ; $i += $p )
$prime [ $i ] = false;
}
function divCount( $n )
{
global $prime ;
$total = 1;
for ( $p = 2; $p <= $n ; $p ++)
{
if ( $prime [ $p ])
{
$count = 0;
if ( $n % $p == 0)
{
while ( $n % $p == 0)
{
$n = $n / $p ;
$count ++;
}
$total = $total * ( $count + 1);
}
}
}
return $total ;
}
function findNumber( $n )
{
if ( $n == 1)
return 3;
$i = 2;
$count = 0;
$second = 1;
$first = 1;
while ( $count <= $n )
{
if ( $i % 2 == 0)
{
$first = divCount( $i + 1);
$count = $first * $second ;
}
else
{
$second = divCount(( $i + 1) / 2);
$count = $first * $second ;
}
$i ++;
}
return $i * ( $i - 1) / 2;
}
$n = 4;
sieve();
echo findNumber( $n );
?>
|
Javascript
<script>
const MAX = 100000;
let prime = new Array(MAX + 1).fill(0);
function sieve()
{
for (i = 0; i <= MAX; i++)
prime[i] = true ;
for (p = 2; p * p < MAX; p++)
if (prime[p] == true )
for (i = p * 2; i < MAX; i += p)
prime[i] = false ;
}
function divCount(n)
{
var total = 1;
for (p = 2; p <= n; p++) {
if (prime[p]) {
var count = 0;
if (n % p == 0) {
while (n % p == 0) {
n = n / p;
count++;
}
total = total * (count + 1);
}
}
}
return total;
}
function findNumber(n) {
if (n == 1)
return 3;
var i = 2;
var count = 0;
var second = 1;
var first = 1;
while (count <= n) {
if (i % 2 == 0) {
first = divCount(i + 1);
count = first * second;
}
else {
second = divCount((i + 1) / 2);
count = first * second;
}
i++;
}
return i * (i - 1) / 2;
}
var n = 4;
sieve();
document.write(findNumber(n));
</script>
|
Time Complexity: O(N*logN),
- Sieve of eratosthenes will cost O(N*log(logN)) time, but
- we are using nested loops where the outer loop traverses N times and the inner loop traverses logN times as in every traversal we are decrementing by floor division of factor of n.
Auxiliary Space: O(105), as we are using extra space for primer array.
Share your thoughts in the comments
Please Login to comment...