結果

問題 No.732 3PrimeCounting
ユーザー Kohei AsanoKohei Asano
提出日時 2020-01-15 09:56:25
言語 Rust
(1.77.0 + proconio)
結果
AC  
実行時間 1,031 ms / 3,000 ms
コード長 11,049 bytes
コンパイル時間 12,815 ms
コンパイル使用メモリ 378,480 KB
実行使用メモリ 24,096 KB
最終ジャッジ日時 2024-06-10 01:27:10
合計ジャッジ時間 28,091 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 1 ms
5,248 KB
testcase_02 AC 1 ms
5,248 KB
testcase_03 AC 1 ms
5,248 KB
testcase_04 AC 0 ms
5,376 KB
testcase_05 AC 1 ms
5,376 KB
testcase_06 AC 1 ms
5,376 KB
testcase_07 AC 1 ms
5,376 KB
testcase_08 AC 1 ms
5,376 KB
testcase_09 AC 1 ms
5,376 KB
testcase_10 AC 1 ms
5,376 KB
testcase_11 AC 1 ms
5,376 KB
testcase_12 AC 1 ms
5,376 KB
testcase_13 AC 1 ms
5,376 KB
testcase_14 AC 1 ms
5,376 KB
testcase_15 AC 1 ms
5,376 KB
testcase_16 AC 1 ms
5,376 KB
testcase_17 AC 1 ms
5,376 KB
testcase_18 AC 1 ms
5,376 KB
testcase_19 AC 1 ms
5,376 KB
testcase_20 AC 4 ms
5,376 KB
testcase_21 AC 13 ms
5,376 KB
testcase_22 AC 12 ms
5,376 KB
testcase_23 AC 1 ms
5,376 KB
testcase_24 AC 1 ms
5,376 KB
testcase_25 AC 26 ms
5,376 KB
testcase_26 AC 21 ms
5,376 KB
testcase_27 AC 5 ms
5,376 KB
testcase_28 AC 6 ms
5,376 KB
testcase_29 AC 10 ms
5,376 KB
testcase_30 AC 10 ms
5,376 KB
testcase_31 AC 12 ms
5,376 KB
testcase_32 AC 20 ms
5,376 KB
testcase_33 AC 21 ms
5,376 KB
testcase_34 AC 21 ms
5,376 KB
testcase_35 AC 22 ms
5,376 KB
testcase_36 AC 21 ms
5,376 KB
testcase_37 AC 3 ms
5,376 KB
testcase_38 AC 3 ms
5,376 KB
testcase_39 AC 21 ms
5,376 KB
testcase_40 AC 13 ms
5,376 KB
testcase_41 AC 13 ms
5,376 KB
testcase_42 AC 13 ms
5,376 KB
testcase_43 AC 12 ms
5,376 KB
testcase_44 AC 12 ms
5,376 KB
testcase_45 AC 7 ms
5,376 KB
testcase_46 AC 6 ms
5,376 KB
testcase_47 AC 11 ms
5,376 KB
testcase_48 AC 26 ms
5,376 KB
testcase_49 AC 26 ms
5,376 KB
testcase_50 AC 12 ms
5,376 KB
testcase_51 AC 12 ms
5,376 KB
testcase_52 AC 5 ms
5,376 KB
testcase_53 AC 54 ms
5,376 KB
testcase_54 AC 454 ms
13,324 KB
testcase_55 AC 463 ms
13,320 KB
testcase_56 AC 457 ms
13,324 KB
testcase_57 AC 118 ms
5,376 KB
testcase_58 AC 117 ms
5,404 KB
testcase_59 AC 56 ms
5,376 KB
testcase_60 AC 205 ms
7,560 KB
testcase_61 AC 202 ms
7,560 KB
testcase_62 AC 465 ms
14,648 KB
testcase_63 AC 254 ms
8,476 KB
testcase_64 AC 208 ms
7,860 KB
testcase_65 AC 208 ms
7,984 KB
testcase_66 AC 1 ms
5,376 KB
testcase_67 AC 2 ms
5,376 KB
testcase_68 AC 505 ms
13,724 KB
testcase_69 AC 516 ms
13,852 KB
testcase_70 AC 466 ms
13,484 KB
testcase_71 AC 464 ms
13,360 KB
testcase_72 AC 262 ms
8,380 KB
testcase_73 AC 580 ms
18,620 KB
testcase_74 AC 584 ms
18,616 KB
testcase_75 AC 26 ms
5,376 KB
testcase_76 AC 457 ms
13,792 KB
testcase_77 AC 120 ms
6,156 KB
testcase_78 AC 566 ms
14,732 KB
testcase_79 AC 470 ms
13,880 KB
testcase_80 AC 566 ms
14,432 KB
testcase_81 AC 469 ms
13,512 KB
testcase_82 AC 5 ms
5,376 KB
testcase_83 AC 117 ms
5,432 KB
testcase_84 AC 205 ms
7,204 KB
testcase_85 AC 481 ms
13,032 KB
testcase_86 AC 583 ms
14,500 KB
testcase_87 AC 1,006 ms
24,092 KB
testcase_88 AC 1,031 ms
24,096 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
warning: unused macro definition: `input`
 --> src/main.rs:1:14
  |
1 | macro_rules! input {
  |              ^^^^^
  |
  = note: `#[warn(unused_macros)]` on by default

warning: unused macro definition: `input_inner`
  --> src/main.rs:17:14
   |
17 | macro_rules! input_inner {
   |              ^^^^^^^^^^^

warning: unused macro definition: `read_value`
  --> src/main.rs:27:14
   |
27 | macro_rules! read_value {
   |              ^^^^^^^^^^

warning: function `mod_pow` is never used
   --> src/main.rs:316:4
    |
316 | fn mod_pow(mut a: u64, mut n: u64, m: u64) -> u64 {
    |    ^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

warning: function `mod_inv` is never used
   --> src/main.rs:330:4
    |
330 | fn mod_inv(a: u64, m: u64) -> u64 {
    |    ^^^^^^^

warning: function `garner` is never used
   --> src/main.rs:333:4
    |
333 | fn garner(mr: &mut Vec<(u64, u64)>, m: u64) -> u64 {
    |    ^^^^^^

ソースコード

diff #

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, ) => {};
    // var... 変数の識別子, $t...型を一つよむ
    ($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, usize1) => {
        read_value!($iter, usize) - 1
    };
    // 配列の最後のNestではここで型が指定されてparseされる
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}
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, ) => {};
    // var... 変数の識別子, $t...型を一つよむ
    ($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, usize1) => {
        read_value!($iter, usize) - 1
    };
    // 配列の最後のNestではここで型が指定されてparseされる
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}
// =========
pub trait ModI:
    Sized
    + PartialEq
    + Copy
    + std::ops::Add<Output = Self>
    + std::ops::Sub<Output = Self>
    + std::ops::Mul<Output = Self>
    + std::ops::Div<Output = Self>
    + std::ops::AddAssign
    + std::ops::SubAssign
    + std::ops::MulAssign
    + std::ops::DivAssign
    + std::default::Default
    + std::fmt::Display
    + std::fmt::Debug
{
    fn m() -> u64;
    fn new(x: u64) -> Self;
    fn pow(self, n: u64) -> Self;
    fn inv(&self) -> Self;
}
macro_rules! define_modint {
    ($n:ident,$m:expr) => {
        #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
        struct $n(u64);

        #[allow(dead_code)]
        impl ModI for $n {
            fn m() -> u64 {
                $m
            }
            fn new(x: u64) -> $n {
                $n(x % $m)
            }

            fn pow(self, mut n: u64) -> $n {
                let mut ret = $n::new(1);
                let mut base = self;
                while n > 0 {
                    if n & 1 == 1 {
                        ret *= base;
                    }
                    base *= base;
                    n >>= 1;
                }
                ret
            }

            fn inv(&self) -> $n {
                self.pow($m - 2)
            }
        }

        impl std::default::Default for $n {
            fn default() -> $n {
                $n::new(0u64)
            }
        }

        impl std::convert::From<u64> for $n {
            fn from(x: u64) -> $n {
                $n::new(x)
            }
        }

        // Binary operator
        impl std::ops::Add for $n {
            type Output = $n;
            fn add(self, rhs: $n) -> Self::Output {
                $n::new(self.0 + rhs.0)
            }
        }

        impl std::ops::Sub for $n {
            type Output = $n;
            fn sub(self, rhs: $n) -> Self::Output {
                if self.0 >= rhs.0 {
                    $n::new(self.0 - rhs.0)
                } else {
                    $n::new($m - rhs.0 + self.0)
                }
            }
        }

        impl std::ops::Mul for $n {
            type Output = $n;
            fn mul(self, rhs: $n) -> Self::Output {
                $n::new(self.0 * rhs.0)
            }
        }

        impl std::ops::Div for $n {
            type Output = $n;
            fn div(self, rhs: $n) -> Self::Output {
                $n::new(self.0 / rhs.0)
            }
        }

        // Assign
        impl std::ops::AddAssign for $n {
            fn add_assign(&mut self, rhs: $n) {
                *self = *self + rhs;
            }
        }

        impl std::ops::SubAssign for $n {
            fn sub_assign(&mut self, rhs: $n) {
                *self = *self - rhs;
            }
        }

        impl std::ops::MulAssign for $n {
            fn mul_assign(&mut self, rhs: $n) {
                *self = *self * rhs;
            }
        }

        impl std::ops::DivAssign for $n {
            fn div_assign(&mut self, rhs: $n) {
                *self = *self / rhs;
            }
        }

        impl std::fmt::Display for $n {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.0)
            }
        }
        impl std::fmt::Debug for $n {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.0)
            }
        }
    };
}
// 10^8 < p < 10^9
// 3 is primitive p-1 root of these
// 167772161 = 5*2^25 + 1, 469762049 = 7*2^26 + 1, 998244353 = 119*2^23 + 1
// 1224736769 = 73 * 2^24 + 1
// define_modint!(ModInt167772161, 167772161);
define_modint!(ModInt998244353, 998244353);
define_modint!(ModInt1224736769, 1224736769);
fn ntt<T: ModI>(a: &mut [T], n: usize, inv: bool) {
    // h = log2(n)
    let h = {
        let mut i = 0;
        while 1 << i != n {
            i += 1;
        }
        i
    };
    let mut j: usize;
    for i in 0..n {
        j = 0;
        for k in 0..h {
            // (i >> k & 1)はiのk桁目のbit
            // (h - 1 - k)は全体をh-bitとしてk桁目の反対の位置
            j |= (i >> k & 1) << (h - 1 - k);
        }
        // はじめの一回だけひっくりかえす
        if i < j {
            a.swap(i, j)
        };
    }
    // バタフライ演算
    let mut b = 1;
    while b < n {
        let zeta: T = T::new(3).pow((T::m() - 1) / (2 * b as u64));
        for j in 0..b {
            // 3 is primitive root of proth prime
            // 3 ^ ((m - 1) / (n * j)) is primitive n root's j power
            let e: T = if inv {
                zeta.pow(j as u64).inv()
            } else {
                zeta.pow(j as u64)
            };
            let mut k = 0;
            while k < n {
                let s: T = a[j + k];
                let t: T = a[j + k + b] * e;
                a[j + k] = s + t;
                a[j + k + b] = s - t;
                k += b * 2;
            }
        }
        b *= 2;
    }

    if inv {
        let ni = T::new(n as u64).inv();
        for i in 0..n {
            a[i] *= ni;
        }
    }
}

fn mod_conv<T: ModI>(mut a: &mut [T], mut b: &mut [T]) -> Vec<T> {
    let n = a.len();
    // calc each mod
    ntt(&mut a, n, false);
    ntt(&mut b, n, false);
    let mut c = Vec::with_capacity(n);
    for i in 0..n {
        c.push(a[i] * b[i]);
    }
    ntt(&mut c, n, true);
    c
}

fn single_convolution<T: ModI>(a: &mut [T], b: &mut [T]) -> Vec<T> {
    let d: usize = a.len() + b.len() - 1;
    let n = d.checked_next_power_of_two().unwrap();
    let mut a = a.to_vec();
    a.resize(n, T::new(0));
    let mut b = b.to_vec();
    b.resize(n, T::new(0));
    let mut res = mod_conv(&mut a, &mut b);
    res.truncate(d);
    res
}
fn mod_pow(mut a: u64, mut n: u64, m: u64) -> u64 {
    let mut ret = 1;
    while n > 0 {
        if n & 1 == 1 {
            ret *= a;
            ret %= m;
        }
        a *= a;
        a %= m;
        n >>= 1;
    }
    ret
}
// mod mの体におけるaの逆元
fn mod_inv(a: u64, m: u64) -> u64 {
    mod_pow(a, m - 2, m)
}
fn garner(mr: &mut Vec<(u64, u64)>, m: u64) -> u64 {
    mr.push((m, 0));
    // coef... mixed radixの係数, constants... 前まで求めた係数
    let mut coef: Vec<u64> = vec![1; mr.len()];
    let mut constants: Vec<u64> = vec![0; mr.len()];
    for i in 0..mr.len() - 1 {
        let v: u64 = (mr[i].1 + mr[i].0 - constants[i]) * mod_inv(coef[i], mr[i].0) % mr[i].0;
        for j in i + 1..mr.len() {
            constants[j] += coef[j] * v;
            constants[j] %= mr[j].0;
            coef[j] *= mr[i].0;
            coef[j] %= mr[j].0;
        }
    }
    constants[mr.len() - 1]
}

fn primes_under(n: u64) -> Vec<u64> {
    let mut primes: Vec<u64> = vec![];
    // 素数定理を使え
    // x/ln(x)
    let mut non_primes = std::collections::HashSet::with_capacity(n as usize / 2);
    for i in 2..((n as f64).sqrt() as u64 + 1) {
        if non_primes.contains(&i) {
            continue;
        } else {
            primes.push(i);
            let mut k = 2;
            while i * k <= n {
                non_primes.insert(i * k);
                k += 1;
            }
        }
    }
    for i in ((n as f64).sqrt() as u64 + 1)..n + 1 {
        if non_primes.contains(&i) {
            continue;
        } else {
            primes.push(i);
        }
    }
    primes
}

fn main() {
    input! {
        n:u64,
    }
    let ps = primes_under(n);
    type F0 = ModInt1224736769;
    let mut a: Vec<F0> = vec![F0::new(0); ps[ps.len() - 1] as usize + 1];
    let mut b: Vec<F0> = vec![F0::new(0); 2 * ps[ps.len() - 1] as usize + 1];
    for p in &ps {
        a[*p as usize] = F0::new(1);
        b[*p as usize * 2] = F0::new(1);
    }
    let mut res0 = a.clone();
    let mut res1 = b.clone();
    // all
    res0 = single_convolution(
        &mut single_convolution(&mut res0, &mut a.clone()),
        &mut a.clone(),
    );
    // two
    res1 = single_convolution(&mut res1, &mut a.clone());

    let ps3 = primes_under(3 * n);
    let mut ans = 0;
    for p in &ps3 {
        let i = *p as usize;
        if i < res1.len() {
            ans += (res0[i].0 - 3 * res1[i].0) / 6;
        } else if i < res0.len() {
            ans += res0[i].0 / 6;
        } else {
            break;
        }
    }
    println!("{:?}", ans);
}
0