点击打开链接
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之间素数的个数。
下边的这个是常规写法,遍历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; }