解法
ナイーブなDPを考えると、遷移する先が区間に分けられ、しかもその区間の数は
であることに気づく。DPの際に区間ごとにまとめて遷移させれば良い。
コード
use mod_int::ModInt;
use std::collections::BTreeSet;
const MOD: usize = 1e9 as usize + 7;
fn main() {
let s = std::io::stdin();
let mut sc = Scanner { stdin: s.lock() };
let n: usize = sc.read();
let k: usize = sc.read();
let mut seg = BTreeSet::new();
for i in 1.. {
if i * i > n {
break;
}
let j = i + 1;
let m = n / j;
let from = m + 1;
let to = n / i;
seg.insert((from, to));
seg.insert((i, i));
}
let seg = seg.into_iter().collect::<Vec<_>>();
let n = seg.len();
let mut dp = vec![ModInt::new(1); n];
for _ in 1..k {
let mut sum = vec![ModInt::new(0); n + 1];
for i in 0..n {
let (from, to) = seg[i];
let tmp = dp[i] * (to - from + 1);
sum[n - i] -= tmp;
sum[0] += tmp;
}
let mut next = vec![ModInt::new(0); n];
let mut cur = ModInt::new(0);
for i in 0..n {
cur += sum[i];
next[i] = cur;
}
dp = next;
}
let mut ans = ModInt::new(0);
for i in 0..n {
let (from, to) = seg[i];
ans += dp[i] * (to - from + 1);
}
println!("{}", ans.0);
}
pub mod mod_int {
use super::MOD;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
type Num = usize;
#[derive(Clone, Copy, Debug)]
pub struct ModInt<T: Copy + Clone>(pub T);
impl Add<ModInt<Num>> for ModInt<Num> {
type Output = ModInt<Num>;
fn add(self, rhs: ModInt<Num>) -> ModInt<Num> {
self + rhs.0
}
}
impl Add<Num> for ModInt<Num> {
type Output = ModInt<Num>;
fn add(self, rhs: Num) -> ModInt<Num> {
let mut t = rhs + self.0;
if t >= MOD {
t = t - MOD;
}
ModInt(t)
}
}
impl Sub<Num> for ModInt<Num> {
type Output = ModInt<Num>;
fn sub(self, rhs: Num) -> ModInt<Num> {
let rhs = if rhs >= MOD { rhs % MOD } else { rhs };
let value = if self.0 < rhs { self.0 + MOD } else { self.0 };
ModInt(value - rhs)
}
}
impl Sub<ModInt<Num>> for ModInt<Num> {
type Output = ModInt<Num>;
fn sub(self, rhs: ModInt<Num>) -> ModInt<Num> {
self - rhs.0
}
}
impl AddAssign<Num> for ModInt<Num> {
fn add_assign(&mut self, other: Num) {
*self = *self + other;
}
}
impl AddAssign<ModInt<Num>> for ModInt<Num> {
fn add_assign(&mut self, other: ModInt<Num>) {
*self = *self + other;
}
}
impl SubAssign<Num> for ModInt<Num> {
fn sub_assign(&mut self, other: Num) {
*self = *self - other;
}
}
impl SubAssign<ModInt<Num>> for ModInt<Num> {
fn sub_assign(&mut self, other: ModInt<Num>) {
*self = *self - other;
}
}
impl Mul<ModInt<Num>> for ModInt<Num> {
type Output = ModInt<Num>;
fn mul(self, rhs: ModInt<Num>) -> ModInt<Num> {
self * rhs.0
}
}
impl Mul<Num> for ModInt<Num> {
type Output = ModInt<Num>;
fn mul(self, rhs: Num) -> ModInt<Num> {
let t = (self.0 * rhs) % MOD;
ModInt(t)
}
}
impl MulAssign<Num> for ModInt<Num> {
fn mul_assign(&mut self, rhs: Num) {
*self = *self * rhs;
}
}
impl MulAssign<ModInt<Num>> for ModInt<Num> {
fn mul_assign(&mut self, rhs: ModInt<Num>) {
*self = *self * rhs;
}
}
impl ModInt<Num> {
pub fn new(value: Num) -> Self {
ModInt(value)
}
pub fn pow(self, e: usize) -> ModInt<Num> {
let mut result = ModInt::new(1);
let mut cur = self;
let mut e = e;
while e > 0 {
if e & 1 == 1 {
result *= cur;
}
e >>= 1;
cur *= cur;
}
result
}
}
}
pub struct Scanner<R> {
stdin: R,
}
impl<R: std::io::Read> Scanner<R> {
pub fn read<T: std::str::FromStr>(&mut self) -> T {
use std::io::Read;
let buf = self
.stdin
.by_ref()
.bytes()
.map(|b| b.unwrap())
.skip_while(|&b| b == b' ' || b == b'\n')
.take_while(|&b| b != b' ' && b != b'\n')
.collect::<Vec<_>>();
unsafe { std::str::from_utf8_unchecked(&buf) }
.parse()
.ok()
.expect("Parse error.")
}
pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
(0..n).map(|_| self.read()).collect()
}
pub fn chars(&mut self) -> Vec<char> {
self.read::<String>().chars().collect()
}
}