Skip to content

Commit 0b05c4a

Browse files
committed
Add an example for ABC156-D
1 parent a58bdd1 commit 0b05c4a

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

examples/abc156-d.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// https://atcoder.jp/contests/abc156/tasks/abc156_d
2+
//
3+
// 以下のクレートを使用。
4+
//
5+
// - `num`
6+
// - `num-traits`
7+
use num::One;
8+
use proconio::input;
9+
10+
use std::fmt::{self, Display};
11+
use std::num::ParseIntError;
12+
use std::ops::{Add, Div, Mul, MulAssign, Sub};
13+
use std::str::FromStr;
14+
15+
fn main() {
16+
// `proconio::input!`。
17+
//
18+
// https://docs.rs/proconio/0.3.6/proconio/macro.input.html
19+
input! {
20+
n: Zp,
21+
a: Zp,
22+
b: Zp,
23+
}
24+
25+
// `num_traits::pow`を使って2^nを求める。
26+
//
27+
// https://docs.rs/num-traits/0.2/num_traits/pow/fn.pow.html
28+
let ans = num::pow(Zp::new(2), n.repr) - binomial(n, a) - binomial(n, b) - Zp::new(1);
29+
println!("{}", ans);
30+
}
31+
32+
fn binomial(n: Zp, k: Zp) -> Zp {
33+
let (mut numer, mut denom) = (n, Zp::new(1));
34+
for i in 2..=k.repr {
35+
numer *= n - Zp::new(i) + Zp::new(1);
36+
denom *= Zp::new(i);
37+
}
38+
numer / denom
39+
}
40+
41+
const P: usize = 1_000_000_007;
42+
43+
#[derive(Debug, Clone, Copy)]
44+
struct Zp {
45+
repr: usize,
46+
}
47+
48+
impl Zp {
49+
fn new(val: usize) -> Self {
50+
Self { repr: val % P }
51+
}
52+
}
53+
54+
impl FromStr for Zp {
55+
type Err = ParseIntError;
56+
57+
fn from_str(s: &str) -> Result<Self, ParseIntError> {
58+
s.parse().map(Self::new)
59+
}
60+
}
61+
62+
// `num_integer::pow`に必要。
63+
impl One for Zp {
64+
fn one() -> Self {
65+
Self { repr: 1 }
66+
}
67+
}
68+
69+
impl Add for Zp {
70+
type Output = Self;
71+
72+
fn add(self, rhs: Self) -> Self {
73+
Self::new(self.repr + rhs.repr)
74+
}
75+
}
76+
77+
impl Sub for Zp {
78+
type Output = Self;
79+
80+
fn sub(self, rhs: Self) -> Self {
81+
let repr = if self.repr < rhs.repr {
82+
P + self.repr - rhs.repr
83+
} else {
84+
self.repr - rhs.repr
85+
};
86+
Self { repr }
87+
}
88+
}
89+
90+
impl Mul for Zp {
91+
type Output = Self;
92+
93+
fn mul(self, rhs: Self) -> Self {
94+
Self::new(self.repr * rhs.repr)
95+
}
96+
}
97+
98+
impl MulAssign for Zp {
99+
fn mul_assign(&mut self, rhs: Self) {
100+
*self = *self * rhs;
101+
}
102+
}
103+
104+
impl Div for Zp {
105+
type Output = Self;
106+
107+
fn div(self, rhs: Self) -> Self {
108+
// Fermatの小定理より。
109+
// `num_integer::Integer::extended_gcd`というのもあるのでこれを使っても良い。
110+
self * num::pow(rhs, P - 2)
111+
}
112+
}
113+
114+
impl Display for Zp {
115+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
116+
Display::fmt(&self.repr, fmt)
117+
}
118+
}

test-examples.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ url = "https://atcoder.jp/contests/abc154/tasks/abc154_e"
177177
matching = "Words"
178178
meta = { using = ["num", "proconio"] }
179179

180+
[examples.abc156-d]
181+
type = "Normal"
182+
name = "ABC156: D - Bouquet"
183+
url = "https://atcoder.jp/contests/abc156/tasks/abc156_d"
184+
matching = "Words"
185+
meta = { using = ["num", "proconio"] }
186+
180187
[examples.agc023-a]
181188
type = "Normal"
182189
name = "AGC023: A - Zero-Sum Ranges"

0 commit comments

Comments
 (0)