题目链接
https://vjudge.net/problem/HDU-2866
题意:
定义一个Special Primes为:对于一个质数p,如果能找到两个正整数n和m,满足n^3+p*n^2=m^3,那么p是Special Primes。
多次查询,每次给一个L,问小于等于L的素数有多少素数是Special Primes。如果没有输出No Special Prime!。
题解
因为p是质数,所以gcd(n,n+p)的值为1或者p,分两种情况考虑,如果值为p,那么设 n=xp,x是正整数。
那么(x^3+x^2)p^3=m^3 ,m=p *(x^3+x^2)^(1/3) 显然,(x^3+x^2)^(1/3)不是整数。所以n不能是p的倍数。
所以n,p互质 ,n^2和(n+p)也互质。
n^2(n+p)=m^3 式子右边每种质因子有3的整数倍个,相应的左边应该也是,设n=A^3, n+p=B^3 ,
那么p=B^3-A^3=(B-A)*(A^2+B^2+AB) ,p是质数,那么 B-A等于1.
那么p=3A^2+3A+1.
所以只要能找到一个正整数A,满足p=3A^2+3A+1.那么p是Special Primes
去处理出所有的Special Primes,求一下前缀和。就可以每次查询在O(1)的时间查询出来。
代码
#include<algorithm>
#include <iostream>
#include<cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e6+6;
bool a[maxn];
int prime[maxn];
int cnt=0;
int sum[maxn];
void init(){
for(int i=2;i<maxn;i++){
if(!a[i]){
prime[cnt++]=i;
for(int j=i+i;j<maxn;j+=i){
a[j]=true;
}
}
}
}
int main(){
init();
for(int i=0;i<cnt;i++){
int x=prime[i];
int j=1;
while(3*j*j+3*j+1<x) j++;
if(3*j*j+3*j+1==x) sum[x]++;
}
for(int i=1;i<maxn;i++) sum[i]+=sum[i-1];
int n;
while(scanf("%d",&n)!=EOF){
if(sum[n]) printf("%d\n",sum[n]);
else printf("No Special Prime!\n");
}
return 0;
}