P1865 A % B Problem (素数筛法,前缀和)
生活随笔
收集整理的這篇文章主要介紹了
P1865 A % B Problem (素数筛法,前缀和)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
區間質數個數
輸入輸出格式
輸入格式:?
一行兩個整數 詢問次數n,范圍m
接下來n行,每行兩個整數 l,r 表示區間
?
輸出格式:?
對于每次詢問輸出個數 t,如l或r?[1,m]輸出 Crossing the line
?
輸入輸出樣例
輸入樣例#1: 復制
2 5 1 3 2 6輸出樣例#1: 復制
2 Crossing the line說明
【數據范圍和約定】
對于20%的數據 1<=n<=10 1<=m<=10
對于100%的數據 1<=n<=1000 1<=m<=1000000 -10^9<=l<=r<=10^9 1<=t<=1000000
第一眼肯定會想到素數篩法,但還需將此算法進行改進。
如果每一次記錄當前這個數之前有幾個是素數,則再求某一區間內的素數個數就變得極為容易。(注意:在求區間[L,? R]內的素數個數時,不能直接用num[R] - num[L],顯然這樣減少一個計算了一個數。
例如:計算區間[2, 8]內的素數個數,
? ? ? ? ?? 數字:1? 2? 3? 4? 5? 6? 7? 8? 9? 10
? ? ?? 前綴和:0? 1? 2? 2? 3? 3? 4 ? 4? 4? 4?
num[8] - num[2] = 4 - 1 = 3,顯然是錯的,所以應該減去他的前一個數的前綴和,即num[R] - num[L-1])
?
素數篩法模板(加計數素數前綴和)
void init(){memset(notprime, false, sizeof(notprime));memset(num, 0, sizeof(num));notprime[0] = notprime[1] = true;num[0] = 0; num[1] = 0;for(int i = 2; i < maxn; i++){if(!notprime[i]){num[i] = num[i-1] + 1;if(i > maxn/i) continue;for(int j = i*i; j < maxn; j += i)notprime[j] = true;}else num[i] = num[i-1];} }?
?
ac代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string>using namespace std; typedef long long LL; const int maxn = 1e6+5;bool notprime[maxn]; int num[maxn];int n, m; int l, r;void init(){memset(notprime, false, sizeof(notprime));memset(num, 0, sizeof(num));notprime[0] = notprime[1] = true;num[0] = 0; num[1] = 0;for(int i = 2; i < maxn; i++){if(!notprime[i]){num[i] = num[i-1] + 1;if(i > maxn/i) continue;for(int j = i*i; j < maxn; j += i)notprime[j] = true;}else num[i] = num[i-1];} }int main() {init();scanf("%d%d", &n, &m);while(n--){scanf("%d%d", &l, &r);if(l < 1||r > m) printf("Crossing the line\n");else printf("%d\n", num[r] - num[l-1]);}return 0; }?
總結
以上是生活随笔為你收集整理的P1865 A % B Problem (素数筛法,前缀和)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 检查是否有负循环(Bellman For
- 下一篇: cell数据类型