-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add yukicoder/2645.rs yukicoder/2725.rs yukicoder/2726.rs
- Loading branch information
Showing
3 changed files
with
187 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use std::cmp::*; | ||
use std::io::Read; | ||
|
||
fn get_word() -> String { | ||
let stdin = std::io::stdin(); | ||
let mut stdin=stdin.lock(); | ||
let mut u8b: [u8; 1] = [0]; | ||
loop { | ||
let mut buf: Vec<u8> = Vec::with_capacity(16); | ||
loop { | ||
let res = stdin.read(&mut u8b); | ||
if res.unwrap_or(0) == 0 || u8b[0] <= b' ' { | ||
break; | ||
} else { | ||
buf.push(u8b[0]); | ||
} | ||
} | ||
if buf.len() >= 1 { | ||
let ret = String::from_utf8(buf).unwrap(); | ||
return ret; | ||
} | ||
} | ||
} | ||
|
||
fn get<T: std::str::FromStr>() -> T { get_word().parse().ok().unwrap() } | ||
|
||
// https://yukicoder.me/problems/no/2645 (3.5) | ||
// 式変形すると、\sum_{i=1}^n \sum{j=1}^{floor(n/i)} 1/(ij) である。 | ||
// 以下をやる必要がある: | ||
// - b_a := \sum_{j=1}^{a} 1/j を高速に求める | ||
// - sqrt(n) との大小で b_a の加算の方法を変える | ||
// b_a - ln(a + 0.5) は O(1/a^2) のはずなので、それを使って誤差を小さくする | ||
// Tags: sqrt-decomposition, sum-of-divisors, harmonic-series | ||
fn main() { | ||
const W: usize = 100_000; | ||
let mut dp = vec![0.0; W]; | ||
for i in 1..W { | ||
dp[i] = dp[i - 1] + 1.0 / i as f64; | ||
} | ||
let f = |x: i64| { | ||
if x < W as i64 { | ||
dp[x as usize] | ||
} else { | ||
(x as f64 + 0.5).ln() + 0.57721_56649_01532_86060 | ||
} | ||
}; | ||
|
||
let n: i64 = get(); | ||
let mut s = 1; | ||
while s * s <= n { | ||
s += 1; | ||
} | ||
s -= 1; | ||
let mut sum = 0.0; | ||
for i in 1..s + 1 { | ||
sum += 1.0 / i as f64 * f(n / i); | ||
} | ||
for i in 1..s + 1 { | ||
let lo = max(s, n / (i + 1)); | ||
let hi = n / i; | ||
if lo < hi { | ||
sum += (f(hi) - f(lo)) as f64 * f(i); | ||
} | ||
} | ||
println!("{}", sum); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use std::io::Read; | ||
|
||
fn get_word() -> String { | ||
let stdin = std::io::stdin(); | ||
let mut stdin=stdin.lock(); | ||
let mut u8b: [u8; 1] = [0]; | ||
loop { | ||
let mut buf: Vec<u8> = Vec::with_capacity(16); | ||
loop { | ||
let res = stdin.read(&mut u8b); | ||
if res.unwrap_or(0) == 0 || u8b[0] <= b' ' { | ||
break; | ||
} else { | ||
buf.push(u8b[0]); | ||
} | ||
} | ||
if buf.len() >= 1 { | ||
let ret = String::from_utf8(buf).unwrap(); | ||
return ret; | ||
} | ||
} | ||
} | ||
|
||
fn get<T: std::str::FromStr>() -> T { get_word().parse().ok().unwrap() } | ||
|
||
fn gcd(x: i64, y: i64) -> i64 { | ||
if x < y { gcd(y, x) } else if y == 0 { x } else { gcd(y, x % y) } | ||
} | ||
|
||
fn win(n: i64) -> bool { | ||
let mut x = 2; | ||
while x < n && n % x == 0 { x += 1; } | ||
gcd(n, x) == 1 | ||
} | ||
|
||
// https://yukicoder.me/problems/no/2725 (3) | ||
// 実験の結果、n = 2, 6, 18, 30, 42, 54, ... で後手必勝、それ以外で先手必勝であることがわかる。 | ||
// これは n = 2, 6 + 12i とみなすことができる。 | ||
// 6+12i が後手必勝なのは、先手は初手で奇数に行くしかなく、後手は 4 に行けば勝てるためである。 | ||
// 他の場合で先手必勝なのもほとんど明らか。(12|N なら初手 5、2|N and not(3|N) なら初手 3 など) | ||
// -> WA。420, 840 が後手必勝であることを見落としていた。 | ||
// 最小の約数でない正の整数が重要で、420 => 8, 840 => 9 だが、 | ||
// これは元々の数と互いに素ではないので初手で行けない。 | ||
fn main() { | ||
let t: i32 = get(); | ||
for _ in 0..t { | ||
let n: i64 = get(); | ||
println!("{}", if win(n) { | ||
"K" | ||
} else { | ||
"P" | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use std::io::Read; | ||
|
||
fn get_word() -> String { | ||
let stdin = std::io::stdin(); | ||
let mut stdin=stdin.lock(); | ||
let mut u8b: [u8; 1] = [0]; | ||
loop { | ||
let mut buf: Vec<u8> = Vec::with_capacity(16); | ||
loop { | ||
let res = stdin.read(&mut u8b); | ||
if res.unwrap_or(0) == 0 || u8b[0] <= b' ' { | ||
break; | ||
} else { | ||
buf.push(u8b[0]); | ||
} | ||
} | ||
if buf.len() >= 1 { | ||
let ret = String::from_utf8(buf).unwrap(); | ||
return ret; | ||
} | ||
} | ||
} | ||
|
||
fn get<T: std::str::FromStr>() -> T { get_word().parse().ok().unwrap() } | ||
|
||
fn main() { | ||
// In order to avoid potential stack overflow, spawn a new thread. | ||
let stack_size = 104_857_600; // 100 MB | ||
let thd = std::thread::Builder::new().stack_size(stack_size); | ||
thd.spawn(|| solve()).unwrap().join().unwrap(); | ||
} | ||
|
||
fn dfs(v: usize, par: usize, g: &Vec<Vec<usize>>, dep: &mut [usize]) { | ||
for &to in &g[v] { | ||
if to == par { continue; } | ||
dep[to] = dep[v] + 1; | ||
dfs(to, v, g, dep); | ||
} | ||
} | ||
|
||
// https://yukicoder.me/problems/no/2726 (3) | ||
// 奇数深さの頂点の値からなる Nim だと思うと AC。 | ||
// Tags: nim, staircase-nim | ||
fn solve() { | ||
let t: i32 = get(); | ||
for _ in 0..t { | ||
let n: usize = get(); | ||
let k: i64 = get(); | ||
let mut g = vec![vec![]; n]; | ||
for _ in 0..n - 1 { | ||
let x = get::<usize>() - 1; | ||
let y = get::<usize>() - 1; | ||
g[x].push(y); | ||
g[y].push(x); | ||
} | ||
let a: Vec<i64> = (0..n).map(|_| get()).collect(); | ||
let mut dep = vec![0; n]; | ||
dfs(0, n, &g, &mut dep); | ||
let mut g = 0; | ||
for i in 1..n { | ||
if dep[i] % 2 == 1 { | ||
g ^= a[i] % (k + 1); | ||
} | ||
} | ||
println!("{}", if g == 0 { "P" } else { "K" }) | ||
} | ||
} |