题目链接:https://vjudge.net/contest/196700#problem/W
题意:给出a,b,a<=n<=b,求当n在区间(a,b)表达式n^2+n+41是素数的比率。
分析:一开始想到用素数筛法,题目中没有给出限制内存,估计没有限制,以前也没有求过1e8以内的素数,于是试了一下,没想到过了。后面看了别人的题解,裸判(打表)居然也可以过,费马小定理和欧拉函数也可以做。于是都试了一遍,都AC了。但是此题的精度有点坑,一直想不通为什么要加个eps(1e-8),我开始以为是保留两位小数不四舍五入,后面试了下也不对,哪位大神知道原因,麻烦说下,评论一下就好,谢谢!
///方法一:素数筛法
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 1e8 + 1e5;
bool vis[maxn];
int a,b,cnt[10005];
void init(){
memset(vis,0,sizeof(vis));
for(int i=2;i*i<maxn;i++)
if(!vis[i])
for(int j=i*i;j<maxn;j+=i)
vis[j]=1;
cnt[0]=1;
for(int i=1;i<10002;i++)
cnt[i]=cnt[i-1]+(vis[i*i+i+41]==0);
}
float slove(){
if(!a) return (float)cnt[b]/(b+1);
return (float)(cnt[b]-cnt[a-1])/(b-a+1);
}
int main(){
init();
while(cin>>a>>b)
printf("%.2f\n",slove()*100+1e-8);
///printf("%.2f\n",(float)((int)(slove()*10000))/100);都不对
///printf("%.2f\n",(slove()-0.00005)*100);
}
///裸判+打表
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int a,b,cnt[10002];
int isPrime(int x){
for(int i=2 ;i*i<=x;i++)
if(x%i==0) return 0;
return 1;
}
void init(){
cnt[0]=1;
for(int i=1;i<10002;i++)
cnt[i]=cnt[i-1]+(isPrime(i*i+i+41)==1);
}
float slove(){
if(!a) return (float)cnt[b]/(b+1);
return (float)(cnt[b]-cnt[a-1])/(b-a+1);
}
int main(){
init();
while(cin>>a>>b)
printf("%.2f\n",slove()*100+1e-8);
}
///费马小定理(快速幂)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int a,b,cnt[10002];
void init(){
memset(cnt,0,sizeof(cnt));
cnt[0]=1;
for(int i=1;i<10002;i++){
long long tmp=i*i+i+40,ans=1,c=2;
int t=tmp+1;
while(tmp){
if(tmp&1) ans=ans*c%t;
c=c*c%t,tmp/=2;
}
cnt[i]=cnt[i-1]+(ans==1);
}
}
float slove(){
if(!a) return (float)cnt[b]/(b+1);
return (float)(cnt[b]-cnt[a-1])/(b-a+1);
}
int main(){
init();
while(cin>>a>>b)
printf("%.2f\n",slove()*100+1e-8);
}
///方法四:欧拉函数法
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int a,b,cnt[10002];
int isPrime(int n){
int ans=n,tmp=n;
for(int i=2;i*i<=n;i++)
while(n%i==0){
ans-=ans/i;
n/=i;
}
if(n>1) ans-=ans/n;
return ans==tmp-1;
}
void init(){
cnt[0]=1;
for(int i=1;i<10002;i++)
cnt[i]=cnt[i-1]+isPrime(i*i+i+41);
}
float slove(){
if(!a) return (float)cnt[b]/(b+1);
return (float)(cnt[b]-cnt[a-1])/(b-a+1);
}
int main(){
init();
while(cin>>a>>b)
printf("%.2f\n",slove()*100+1e-8);
}