【代碼超詳解】UVA 10200 Prime Time(質數的判定、打表、卡精度,20 ms)(附:線性篩質數模板 + 質數判定模板)

一、題目描述

在這裏插入圖片描述

二、算法分析說明與代碼編寫指導

設 f(n) = n^2 + n + 41,打表 n 從 0 到 10000 累計的質數 f(n) 的數量,記爲數列 c。
每次詢問 [a, b] 返回 c[b] - c[a - 1] 就是區間內含有質數的數量。但是 a、b 可以等於 0,訪問 c[-1] 可能會出錯。所以,改成 c[b] - c[a] + isprime(c[a])。用一個 bitset 來存儲每個 f(n) 是否爲質數,n = 0,1,2,……,10000。
最後輸出的答案要轉換成概率,而且輸出的是百分比,還要加上 1e-5(其它一些數也許也可以),否則會 WA。不過我們隊長說這種題面不講但會卡精度的在老題目中才常見。

三、AC 代碼(20 ms)

在這裏插入圖片描述

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<bitset>
#pragma warning(disable:4996)
using namespace std;
unsigned a, b, c[10001]; bitset<16384> isPrime;
unsigned prime[2048], _PrimeTy, MaxPrime, * prime_end = prime; bitset<16384> notprime;
inline void gen_prime() {
	decltype(_PrimeTy) n = notprime.size() - 1, m = n / 2, L; notprime[0] = notprime[1] = true;
	for (decltype(_PrimeTy) i = 2; i <= m; ++i) {
		if (!notprime[i]) { *prime_end = i, ++prime_end; }
		L = n / i;
		for (auto j = prime; j != prime_end && *j <= L; ++j) {
			notprime[i * *j] = true; if (i % *j == 0)break;
		}
	}
	for (decltype(_PrimeTy) i = m + 1; i <= n; ++i)
		if (!notprime[i]) { *prime_end = i, ++prime_end; }
	MaxPrime = *(prime_end - 1);
}
template<class _Ty> inline bool isprime(const _Ty& x) {
	if (x < notprime.size())return !notprime[x];
	decltype(_PrimeTy) t = min((decltype(_PrimeTy))sqrt(x), MaxPrime);
	for (auto i = prime; i != prime_end; ++i) { if (x % *i == 0)return false; }
	return true;
}
inline unsigned f(const unsigned& n) { return n * n + n + 41; }
int main() {
	gen_prime(); isPrime[0] = true; c[0] = 1;
	for (unsigned i = 1; i <= 10000; ++i) {
		c[i] = c[i - 1]; if (isprime(f(i))) { ++c[i]; isPrime[i] = true; }
	}
	for (;;) {
		if (scanf("%u%u", &a, &b) == EOF)return 0;
		printf("%.2lf\n", 100.0 * (c[b] - c[a] + isPrime[a]) / (b - a + 1) + 1e-5);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章