Luogu1835 素数密度_NOI导刊2011提高(04
这题有两种做法,一种是 Miller-Rabin 直接暴力做
还有一种是正解的筛法
先说 Miller-Rabin
就直接上板子就行了
但是 1e6 带一堆 log 显然不稳
就 “记忆化” 一下,把每个询问过的数字的倍数直接处理掉
直接上真的会 T
直接把询问过的数字倍数的抹掉就能过了
其实应该是把质数的倍数抹掉感觉能少一点常数
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cctype> #include <cstdio> using namespace std; typedef long long ll; const int MAX_SIZ = 2000005; int lef, rig, ans; int prime[3] = {2, 7, 61}; bool not_prime[MAX_SIZ]; inline int fast_pow( int bot, int top, int mod) { register int ret = 1; while (top) { if (top & 1) ret = 1ll * ret * bot % mod; top >>= 1; bot = 1ll * bot * bot % mod; } return ret; } inline bool dvd_chk( int bot, int top, int mod) { register int tmp; while (!(top & 1)) { tmp = fast_pow(bot, top, mod); if (tmp == 1) top >>= 1; else if (tmp == mod - 1) return true ; else return false ; } return true ; } inline bool Test( int a) { if (a <= 1) return false ; if (a == 2) return true ; if (!(a & 1)) return false ; for ( int i = 0; i < 3; ++i) { if (prime[i] == a) return true ; if (fast_pow(prime[i], a - 1, a) != 1) return false ; if (!dvd_chk(prime[i], a - 1, a)) return false ; } return true ; } int main() { scanf ( "%d%d" , &lef, &rig); register ll tmp; for (ll i = lef; i <= rig; ++i) { if (not_prime[i - lef] || i == 1) continue ; if (Test(i)) { ++ans; tmp = (2ll * i); while (tmp <= rig) { not_prime[tmp - lef] = true ; tmp += tmp; } } else not_prime[i - lef] = true ; } printf ( "%d\n" , ans); return 0; } |
然后是正解的做法
直接线性筛肯定是不可行的
考虑怎么搞掉特别大的合数
2147483647 的 mindiv 也不过才 46341
所以直接用 mindiv 去删掉区间内的数就行了,其他的数不用管
这样它大概是个 len * ln len 的
由于这并不是调和级数,分母都是质数,而且并不是 1e6 内的所有
所以它还要小很多
总之比 n log n 快
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cctype> #include <cstdio> #include <cmath> using namespace std; typedef long long ll; const int MAX_SQRT = 65536, MAX_N = 1000005; int lef, rig, tot_prime, ans; int prime[MAX_SQRT]; bool not_prime[MAX_SQRT], GG[MAX_N]; inline void get_prime( int top) { not_prime[1] = true ; for (ll i = 2; i <= top; ++i) { if (!not_prime[i]) prime[++tot_prime] = i; for ( int j = 1; j <= tot_prime && 1ll * i * prime[j] <= top; ++j) { not_prime[i * prime[j]] = true ; if (i % prime[j] == 0) break ; } } return ; } int main() { get_prime(46341); scanf ( "%d%d" , &lef, &rig); for ( int i = 1; i <= tot_prime && prime[i] <= rig; ++i) { for (ll j = ll( ceil ( double (lef) / prime[i])) * prime[i]; j <= rig; j += prime[i]) { if (j != prime[i]) GG[j - lef] = true ; } } for (ll i = lef; i <= rig; ++i) ans += (!GG[i - lef]); printf ( "%d\n" , ans); return 0; } |
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步