結果
問題 | No.1661 Sum is Prime (Hard Version) |
ユーザー | akakimidori |
提出日時 | 2021-08-27 21:56:27 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 351 ms / 3,000 ms |
コード長 | 5,212 bytes |
コンパイル時間 | 25,856 ms |
コンパイル使用メモリ | 404,600 KB |
実行使用メモリ | 21,076 KB |
最終ジャッジ日時 | 2024-11-21 02:14:28 |
合計ジャッジ時間 | 16,027 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,816 KB |
testcase_01 | AC | 1 ms
6,820 KB |
testcase_02 | AC | 228 ms
20,760 KB |
testcase_03 | AC | 1 ms
6,816 KB |
testcase_04 | AC | 1 ms
6,820 KB |
testcase_05 | AC | 1 ms
6,816 KB |
testcase_06 | AC | 1 ms
6,816 KB |
testcase_07 | AC | 1 ms
6,820 KB |
testcase_08 | AC | 1 ms
6,820 KB |
testcase_09 | AC | 1 ms
6,820 KB |
testcase_10 | AC | 1 ms
6,820 KB |
testcase_11 | AC | 1 ms
6,816 KB |
testcase_12 | AC | 203 ms
19,644 KB |
testcase_13 | AC | 198 ms
17,656 KB |
testcase_14 | AC | 225 ms
17,568 KB |
testcase_15 | AC | 294 ms
21,044 KB |
testcase_16 | AC | 243 ms
19,408 KB |
testcase_17 | AC | 219 ms
19,612 KB |
testcase_18 | AC | 93 ms
12,032 KB |
testcase_19 | AC | 170 ms
13,620 KB |
testcase_20 | AC | 102 ms
11,888 KB |
testcase_21 | AC | 188 ms
21,076 KB |
testcase_22 | AC | 144 ms
12,728 KB |
testcase_23 | AC | 351 ms
21,068 KB |
ソースコード
struct FenwickTree { val: Vec<usize>, } impl FenwickTree { fn new(n: usize) -> Self { FenwickTree { val: vec![0; n + 1], } } fn add(&mut self, mut x: usize, v: usize) { while let Some(p) = self.val.get_mut(x) { *p = p.wrapping_add(v); x += x & (!x + 1); } } fn sum(&mut self, mut x: usize) -> usize { assert!(x < self.val.len()); let mut ans = 0usize; while x > 0 { ans = ans.wrapping_add(self.val[x]); x -= x & (!x + 1); } ans } } // N 以下の素数を列挙 fn sieve(n: usize) -> Vec<usize> { let mut is_prime = vec![true; n + 1]; for i in 2.. { if i * i > n { break; } if is_prime[i] { let mut j = i * i; while j <= n { is_prime[j] = false; j += i; } } } let len = is_prime.iter().skip(2).filter(|p| **p).count(); let mut prime = Vec::with_capacity(len); for (i, is_prime) in is_prime.into_iter().enumerate().skip(2) { if is_prime { prime.push(i); } } prime } // N 以下の素数の個数を数える fn prime_count(n: usize) -> usize { if n <= 1 { return 0; } let mut m = 1; while (m + 1) * (m + 1) <= n { m += 1; } let prime = sieve(m); let bound = (n as f64 / (n as f64 + 10.0).log10()).cbrt().powi(2) as usize + 1; let batch = (n as f64).sqrt() as usize + 1; let mut ans = prime.len() - 1; let mut query = vec![vec![]; bound / batch + 1]; let mut stack = vec![(n, prime.len(), 1usize)]; while let Some((n, k, sign)) = stack.pop() { if k == 0 { ans = ans.wrapping_add(sign.wrapping_mul(n)); continue; } let p = prime[k - 1]; if p * p > n { let x = match prime[..k].binary_search_by(|p| p.pow(2).cmp(&n)) { Ok(k) => k + 1, Err(k) => k, }; ans = ans.wrapping_sub(sign.wrapping_mul(k - x)); stack.push((n, x, sign)); } else if n <= bound { query[n / batch].push((n, k, sign)); } else { stack.push((n, k - 1, sign)); stack.push((n / p, k - 1, !sign + 1)); } } let mut sum = vec![0; prime.len()]; for (i, mut query) in query.into_iter().enumerate() { query.sort_by_key(|p| !p.1); let left = i * batch; let right = (i + 1) * batch; let mut is_prime = vec![true; batch]; let mut bit = FenwickTree::new(batch); for i in 1..=batch { bit.add(i, 1); } for (i, &p) in prime.iter().enumerate() { if p >= right { break; } let mut k = (left + p - 1) / p * p; while k < right { let x = k - left; if is_prime[x] { is_prime[x] = false; bit.add(x + 1, !0); } k += p; } while let Some(&(n, k, sign)) = query.last() { if k == i + 1 { let x = n - left; ans = ans.wrapping_add(sign.wrapping_mul(sum[i] + bit.sum(x + 1))); query.pop(); } else { break; } } sum[i] += bit.sum(batch); } } ans } // ---------- begin input macro ---------- // reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); input_inner!{iter, $($r)*} }; ($($r:tt)*) => { let s = { use std::io::Read; let mut s = String::new(); std::io::stdin().read_to_string(&mut s).unwrap(); s }; let mut iter = s.split_whitespace(); input_inner!{iter, $($r)*} }; } macro_rules! input_inner { ($iter:expr) => {}; ($iter:expr, ) => {}; ($iter:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($iter, $t); input_inner!{$iter $($r)*} }; } macro_rules! read_value { ($iter:expr, ( $($t:tt),* )) => { ( $(read_value!($iter, $t)),* ) }; ($iter:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>() }; ($iter:expr, chars) => { read_value!($iter, String).chars().collect::<Vec<char>>() }; ($iter:expr, bytes) => { read_value!($iter, String).bytes().collect::<Vec<u8>>() }; ($iter:expr, usize1) => { read_value!($iter, usize) - 1 }; ($iter:expr, $t:ty) => { $iter.next().unwrap().parse::<$t>().expect("Parse error") }; } // ---------- end input macro ---------- fn run() { input!(l: usize, r: usize); let mut ans = 0; ans += prime_count(r); ans -= prime_count(l - 1); if r - l >= 1 { ans += prime_count(2 * r - 1); ans -= prime_count(2 * l); } println!("{}", ans); } fn main() { run(); }