D - 2017-like Number
Time limit : 2sec / Memory limit : 256MB
Score : 400 points
Problem Statement
We say that a odd number N is similar to 2017 when both N and (N+1)⁄2 are prime.
You are given Q queries.
In the i-th query, given two odd numbers li and ri, find the number of odd numbers x similar to 2017 such that li≤x≤ri.
Constraints
- 1≤Q≤105
- 1≤li≤ri≤105
- li and ri are odd.
- All input values are integers.
Input
Input is given from Standard Input in the following format:
Q l1 r1 : lQ rQ
Output
Print Q lines. The i-th line (1≤i≤Q) should contain the response to the i-th query.
Sample Input 1
1 3 7
Sample Output 1
2
- 3 is similar to 2017, since both 3 and (3+1)⁄2=2 are prime.
- 5 is similar to 2017, since both 5 and (5+1)⁄2=3 are prime.
- 7 is not similar to 2017, since (7+1)⁄2=4 is not prime, although 7 is prime.
Thus, the response to the first query should be 2.
Sample Input 2
4 13 13 7 11 7 11 2017 2017
Sample Output 2
1 0 0 1
Note that 2017 is also similar to 2017.
Sample Input 3
6 1 53 13 91 37 55 19 51 73 91 13 49
Sample Output 3
4 4 1 1 1 2
下边的这个是常规写法,遍历L~R,每个数都判断一遍。 这个肯定会超时
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <list>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
int fun(int x)
{
int w=sqrt(x);
for(int i=2;i<=w;i++)
if(x%i==0)
return 0;
return 1;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int l,r;
cin>>l>>r;
int ans=0;
if(l%2==0)
l++;
for(int i=l;i<=r;i+=2)
{
if(fun(i)&&fun((i+1)/2))
{
ans++;
}
}
cout<<ans<<endl;
}
return 0;
}
但是这是多组数据,时间2s,看似很长,其实很短。
由于种种原因,我需要预处理,把素数不是素数区分做标记,这样先处理一次就行了,就避免了重复计算了。
这个就是——素数筛选法
#include <bits/stdc++.h>
using namespace std;
const int n=1e5+1;
int c[n],s[n];
int main()
{
for(int i=2;i<n;i++)//素数筛选法,不是素数的标记为1
{
if(!c[i])
{
if(i!=2&&!c[(i+1)/2])
s[i]=1;
for(int j=i+i;j<n;j+=i)
c[j]=1;
}
}
for(int i=2;i<n;i++)//记录此坐标与之前的值素数个数
{
s[i]+=s[i-1];
}
int q;
cin>>q;
while(q--)//q次查询
{
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;//l与r之间的素数个数
}
return 0;
}