I'm solving a problem.
Problem Link:
http://www.codechef.com/NOV13/problems/PRETNUM
The Problem is about counting the numbers having their divisor count prime (numbers having their number of divisors prime) in the given range of L and R. 1<=L<=R<=10^12 and L-R<=10^6
My code gives correct output for input less than 10^10. But for numbers greater than 10^10, the answer is either 1 less or 1 greater than correct answer. I'm not able to figure out what the problem might be. My Solution:
/*
* Problem link: http://www.codechef.com/NOV13/problems/PRETNUM
* Approach: Using Segmented Sieve to generate primes, and counting divisors
* for perfect squares.
* Abhishek Kannojia
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PLIMIT 78500
#define NLIMIT 1000000
typedef unsigned long long int ull;
int primes[PLIMIT], maxp;
//Precomputing Pirmes upto 10^6
int precompute() {
unsigned long i, j, k;
int *numbers;
numbers=(int *)malloc(sizeof(int)*NLIMIT+2);
for(i=2; i<NLIMIT; i++)
numbers[i]=1;
//Sieving Primes
for(i=2; i<=NLIMIT; i++) {
if(numbers[i]) {
for (j=i+i;j<=NLIMIT;j+=i) {
numbers[j]=0;
}
}
}
k=0;//printf("\nGenerated Prime:\n");
for(i=2; i<NLIMIT; i++)
if(numbers[i]) {primes[k++]=i; /*printf("%d\n",i);*/}
free(numbers);
return k;
}
int isprime(int n)
{
int i=0;
if(n==0) return 0;
for(i=0; i<=maxp; i++) {
if(primes[i]==n) return 1;
}
return 0;
}
// Counting Number of Divisors based on the fact that
// if prime factorisation of n = (p)^a * (q)^b * (r)^c
// then number of divisors will be (a+1)*(b+1)*(c+1)
int divcount(ull num)
{
int i=0, count=1, n, power;
if(num==1) return 0;
while(num>1 && i<maxp) {
n=primes[i];
power=0;
while(num%n==0) {
num /= n;
power++;
}
count = count*(power+1);
i++;
}
//
// This case handles when on of the prime factor is greater than 10^6
// which does not fall in precomputed array. But we are sure that only
// one such prime exists for (n<10^12). So we mulitply result by (1+1)
//
if(num>1) count*=2;
return count;
}
int calculate(ull l, ull r)
{
int i, j, k, n, m, count=0, *numbers;
ull p;
m=ceil(sqrt(l));
n=floor(sqrt(r));
// If l and r less than 10^6. Directly count from precomputed array.
// The count of divisor is only checked for perfect squares.
if(r<=NLIMIT) {
for(i=0; primes[i]<=r; i++) {
if(primes[i]>=l) count++;
}
while(m<=n) {
if(isprime(divcount(m*m))) count++;
m++;
}
}
else {
for(i=0; i<maxp; i++) if(primes[i]>=l) count++;
for(i=0; i<maxp;) if(primes[i++]>=r) break;
k=i;
// Sieving primes Using Segmented Sieve
numbers = (int *)malloc(sizeof(int)*(r-l+1));
i=0;
for(p=l; p<=r; p++) numbers[i++]=1;
n=i;
for(i=0; i<k; i++) {
if(l%primes[i]==0) j=0;
else j=primes[i]-(l%primes[i]);
for(;j<n; j+=primes[i]) {
if(numbers[j]) {
numbers[j]=0;
}
}
}
for(i=0; i<n; i++)
if(numbers[i]) count++;
n=sqrt(r);
while(m<=n) {
if(isprime(divcount(m*m))==1) count++;
m++;
}
}
return count;
}
int main(){
int tc, i, c;
ull l, r;
maxp=precompute();
scanf("%d",&tc);
while(tc--)
{
scanf("%llu %llu",&l,&r);
c=calculate(l,r);
printf("%d\n",c);
}
return 0;
}
My approach is to first count all primes in given range(Since they have divisor count of 2, which is prime) and then checking divisor count of perfect squares in range because only perfect squares can have prime divisor count.
To count the primes I used Segmented Sieve Approach. To count the divisors for perfect squares I used the fact that if a number N having prime factorisation N = (p)^a * (q)^b * (r)^c then number of divisors for N will be (a+1)(b+1)(c+1) [https://stackoverflow.com/a/110365 ]
Can Anyone help me with this..