結果
| 問題 |
No.117 組み合わせの数
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 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 |
ソースコード
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());
}
}
}