Skip to content

Instantly share code, notes, and snippets.

@aymkx
Last active October 23, 2019 23:28
Show Gist options
  • Save aymkx/833ef7ea3be0b188139477596ececa24 to your computer and use it in GitHub Desktop.
Save aymkx/833ef7ea3be0b188139477596ececa24 to your computer and use it in GitHub Desktop.
二項係数を求めるやつを雑に作った(多倍長整数に対応しました)
extern crate num_bigint;
pub struct Combination {
pascal: Vec<Vec<num_bigint::BigUint>>,
}
impl Combination {
pub fn init() -> Combination {
use num_bigint::ToBigUint;
Combination{
pascal: {
let mut pascal = Vec::new();
pascal.push({
let mut eight = Vec::new();
eight.push(70u32.to_biguint().unwrap());
eight
});
pascal
}
}
}
pub fn comb(&mut self, n: usize, r: usize) -> Option<num_bigint::BigUint> {
use num_bigint::ToBigUint;
if n < r {
return None
}
let r = std::cmp::min(r, n-r);
// nCr -> aCb
let a: num_bigint::BigUint = n.to_biguint().unwrap();
Some(if r == 0 {
1u32.to_biguint().unwrap()
} else if r == 1 {
a
} else if r == 2 {
&a * (&a - 1u32.to_biguint().unwrap()) / 2u32.to_biguint().unwrap()
} else if r == 3 {
&a * (&a - 1u32.to_biguint().unwrap()) * (&a - 2u32.to_biguint().unwrap()) / 6u32.to_biguint().unwrap()
} else {
self.calc(n);
self.pascal[n - 8][r - 4].clone()
})
}
fn calc(&mut self, row: usize) {
use num_bigint::ToBigUint;
// current_rows is 8 initially
let current_rows = self.pascal.len() + 7;
if row <= current_rows {
return;
}
// n is from 9 to p as pCq
for n in (current_rows + 1)..(row + 1) {
self.pascal.push(Vec::new());
let a = (n-1).to_biguint().unwrap();
let x = &a * (&a - 1u32.to_biguint().unwrap())
* (&a - 2u32.to_biguint().unwrap())
/ 6u32.to_biguint().unwrap()
+ &self.pascal[n - 9][0];
self.pascal[n - 8].push(x);
for r in 5..((n+1)/2) {
let x = &self.pascal[n - 9][r - 5] + &self.pascal[n - 9][r - 4];
self.pascal[n - 8].push(x);
}
if n % 2 == 0 {
let x = &self.pascal[n - 9][n/2 - 5] * 2u32.to_biguint().unwrap();
self.pascal[n - 8].push(x);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment