我正在解决一个问题。
问题链接:
http://www.codechef.com/NOV13/problems/PRETNUM
问题是关于在 L 和 R 的给定范围内计算除数素数的数字(除数素数的数字)。 1<=L<=R<=10^12 和 LR<=10^6
我的代码为小于 10^10 的输入提供了正确的输出。但是对于大于 10^10 的数字,答案要么比正确答案小 1,要么比正确答案大 1。我无法弄清楚问题可能是什么。我的解决方案:
/*
* 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;
}
我的方法是首先计算给定范围内的所有素数(因为它们的除数为 2,这是素数),然后检查范围内完美平方的除数,因为只有完美的平方才能有素数除数。
为了计算素数,我使用了分段筛法。为了计算完美平方的除数,我使用了这样一个事实:如果一个数 N 具有素因数分解 N = (p)^a * (q)^b * (r)^c 那么 N 的除数将是 (a+1 ) (b+1) (c+1) [ https://stackoverflow.com/a/110365 ]
谁能帮我这个..