結果

問題 No.117 組み合わせの数
ユーザー Ratstar216
提出日時 2025-09-18 18:46:17
言語 Rust
(1.83.0 + proconio)
結果
RE  
実行時間 -
コード長 3,782 bytes
コンパイル時間 13,359 ms
コンパイル使用メモリ 398,036 KB
実行使用メモリ 19,148 KB
最終ジャッジ日時 2025-09-18 18:46:32
合計ジャッジ時間 13,568 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other RE * 1
権限があれば一括ダウンロードができます

ソースコード

diff #

use proconio::{fastout, input};

pub fn mod_pow(mut a: i64, mut b: i64, modulus: i64) -> i64 {
    if modulus == 1 {
        return 0;
    }
    a = ((a % modulus) + modulus) % modulus;
    let mut result = 1;

    while b > 0 {
        if b & 1 == 1 {
            result = (result * a) % modulus;
        }
        a = (a * a) % modulus;
        b >>= 1;
    }
    result
}


pub fn factorial(n: usize, modulus: i64) -> i64 {
    if modulus == 1 {
        return 0;
    }

    let mut result = 1 % modulus;
    for i in 1..=n {
        result = (result * (i as i64 % modulus)) % modulus;
    }
    result
}

pub fn mod_inv(a: i64, modulus: i64) -> Option<i64> {
    let (g, x, _) = extended_gcd(a, modulus);
    if g != 1 && g != -1 {
        return None;
    }
    let inv = x.rem_euclid(modulus);
    Some(inv)
}

fn extended_gcd(a: i64, b: i64) -> (i64, i64, i64) {
    if b == 0 {
        (a, 1, 0)
    } else {
        let (g, x, y) = extended_gcd(b, a % b);
        (g, y, x - (a / b) * y)
    }
}

/// Pre-computes factorials and inverse factorials modulo a positive integer.
#[derive(Clone, Debug)]
pub struct ModCombinatorics {
    modulus: i64,
    fact: Vec<i64>,
    inv_fact: Vec<i64>,
}

impl ModCombinatorics {
    pub fn new(limit: usize, modulus: i64) -> Option<Self> {

        let mut fact = vec![1 % modulus; limit + 1];
        for i in 1..=limit {
            fact[i] = fact[i - 1] * (i as i64 % modulus) % modulus;
        }

        let mut inv_fact = vec![0; limit + 1];
        inv_fact[limit] = mod_inv(fact[limit], modulus)?;
        for i in (1..=limit).rev() {
            inv_fact[i - 1] = inv_fact[i] * (i as i64 % modulus) % modulus;
        }

        Some(Self {
            modulus,
            fact,
            inv_fact,
        })
    }

    pub fn modulus(&self) -> i64 {
        self.modulus
    }

    pub fn fact(&self, n: usize) -> i64 {
        self.fact[n]
    }

    /// Computes `nPk mod modulus` when `n >= k`.
    pub fn permutation(&self, n: usize, k: usize) -> Option<i64> {
        if k > n {
            return Some(0);
        }
        if n >= self.fact.len() {
            return None;
        }
        Some(self.fact[n] * self.inv_fact[n - k] % self.modulus)
    }

    pub fn combination(&self, n: usize, k: usize) -> Option<i64> {
        if k > n {
            return Some(0);
        }
        if n >= self.fact.len() {
            return None;
        }
        let numerator = self.fact[n];
        let denom = self.inv_fact[k] * self.inv_fact[n - k] % self.modulus;
        Some(numerator * denom % self.modulus)
    }


    pub fn homogeneous(&self, n: usize, k: usize) -> Option<i64> {
        if k == 0 {
            return Some(1);
        }
        if n == 0 {
            return Some(0);
        }
        let total = n.checked_add(k)?.checked_sub(1)?;
        if total >= self.fact.len() {
            return None;
        }
        self.combination(total, k)
    }
}

#[fastout]
fn main() {
    input! {
        t: usize
    }
    const MOD: i64 = 1_000_000_007;
    let comb = ModCombinatorics::new(1000000, MOD).unwrap();
    for _ in 0..t {
        input! {
            s: String
        }
        let open = s.find('(').unwrap();
        let comma = s.find(',').unwrap();
        let close = s.find(')').unwrap();

        let x = &s[..open];
        let a_str = &s[open+1 .. comma];
        let b_str = &s[comma+1 .. close];

        let a: usize = a_str.parse().unwrap();
        let b: usize = b_str.parse().unwrap();

        if x == "C" {
            println!("{}", comb.combination(a, b).unwrap());
        } else if x == "P" {
            println!("{}", comb.permutation(a, b).unwrap());
        } else if x == "H" {
            println!("{}", comb.homogeneous(a, b).unwrap());
        }
    }
}
0