Submission #17140075


Source Code Expand

use std::cmp::Ordering;
use std::collections::HashMap;
use std::hash::Hash;

trait Dfa {
    type Alphabet;
    type State;
    fn init(&self) -> Self::State;
    fn next(&self, s: Self::State, a: Self::Alphabet, i: usize) -> Self::State;
    fn accept(&self, s: Self::State) -> bool;
    fn successful(&self, _: Self::State) -> bool {
        false
    }
    fn unsuccessful(&self, _: Self::State) -> bool {
        false
    }
}

struct And<X, Y>(X, Y);

impl<X: Dfa<Alphabet = A>, Y: Dfa<Alphabet = A>, A: Copy> Dfa for And<X, Y> {
    type Alphabet = A;
    type State = (X::State, Y::State);
    fn init(&self) -> Self::State {
        (self.0.init(), self.1.init())
    }
    fn next(&self, (s0, s1): Self::State, a: Self::Alphabet, i: usize) -> Self::State {
        (self.0.next(s0, a, i), self.1.next(s1, a, i))
    }
    fn accept(&self, (s0, s1): Self::State) -> bool {
        self.0.accept(s0) && self.1.accept(s1)
    }
    fn successful(&self, (s0, s1): Self::State) -> bool {
        self.0.successful(s0) && self.1.successful(s1)
    }
    fn unsuccessful(&self, (s0, s1): Self::State) -> bool {
        self.0.unsuccessful(s0) || self.1.unsuccessful(s1)
    }
}

struct Not<X>(X);

impl<X: Dfa> Dfa for Not<X> {
    type Alphabet = X::Alphabet;
    type State = X::State;
    fn init(&self) -> Self::State {
        self.0.init()
    }
    fn next(&self, s: Self::State, a: Self::Alphabet, i: usize) -> Self::State {
        self.0.next(s, a, i)
    }
    fn accept(&self, s: Self::State) -> bool {
        !self.0.accept(s)
    }
    fn successful(&self, s: Self::State) -> bool {
        self.0.unsuccessful(s)
    }
    fn unsuccessful(&self, s: Self::State) -> bool {
        self.0.successful(s)
    }
}

struct Lt<'a>(&'a [u8]);

impl Dfa for Lt<'_> {
    type Alphabet = u8;
    type State = Ordering;
    fn init(&self) -> Self::State {
        Ordering::Equal
    }
    // assumes i moves from 0 to self.0.len() - 1
    fn next(&self, s: Self::State, a: Self::Alphabet, i: usize) -> Self::State {
        s.then(a.cmp(&self.0[i]))
    }
    fn accept(&self, s: Self::State) -> bool {
        matches!(s, Ordering::Less)
    }
    fn successful(&self, s: Self::State) -> bool {
        matches!(s, Ordering::Less)
    }
    fn unsuccessful(&self, s: Self::State) -> bool {
        matches!(s, Ordering::Greater)
    }
}

struct Leq<'a>(&'a [u8]);

impl Dfa for Leq<'_> {
    type Alphabet = u8;
    type State = Ordering;
    fn init(&self) -> Self::State {
        Ordering::Equal
    }
    // assumes i moves from 0 to self.0.len() - 1
    fn next(&self, s: Self::State, a: Self::Alphabet, i: usize) -> Self::State {
        s.then(a.cmp(&self.0[i]))
    }
    fn accept(&self, s: Self::State) -> bool {
        s != Ordering::Greater
    }
    fn successful(&self, s: Self::State) -> bool {
        s == Ordering::Less
    }
    fn unsuccessful(&self, s: Self::State) -> bool {
        s == Ordering::Greater
    }
}

struct Prod<X, Y>(X, Y);

impl<X: Dfa, Y: Dfa> Dfa for Prod<X, Y> {
    type Alphabet = (X::Alphabet, Y::Alphabet);
    type State = (X::State, Y::State);
    fn init(&self) -> Self::State {
        (self.0.init(), self.1.init())
    }
    fn next(&self, (s0, s1): Self::State, (a0, a1): Self::Alphabet, i: usize) -> Self::State {
        (self.0.next(s0, a0, i), self.1.next(s1, a1, i))
    }
    fn accept(&self, (s0, s1): Self::State) -> bool {
        self.0.accept(s0) && self.1.accept(s1)
    }
    fn successful(&self, (s0, s1): Self::State) -> bool {
        self.0.successful(s0) && self.1.successful(s1)
    }
    fn unsuccessful(&self, (s0, s1): Self::State) -> bool {
        self.0.unsuccessful(s0) || self.1.unsuccessful(s1)
    }
}

struct SameMsb;

impl Dfa for SameMsb {
    type Alphabet = (u8, u8);
    type State = Option<bool>;
    fn init(&self) -> Self::State {
        None
    }
    fn next(&self, s: Self::State, (a0, a1): Self::Alphabet, _: usize) -> Self::State {
        if s.is_none() && (a0 != b'0' || a1 != b'0') {
            Some(a0 == a1)
        } else {
            s
        }
    }
    fn accept(&self, s: Self::State) -> bool {
        s != Some(false)
    }
    fn successful(&self, s: Self::State) -> bool {
        s == Some(true)
    }
    fn unsuccessful(&self, s: Self::State) -> bool {
        s == Some(false)
    }
}

struct Subset;

impl Dfa for Subset {
    type Alphabet = (u8, u8);
    type State = bool;
    fn init(&self) -> Self::State {
        true
    }
    fn next(&self, s: Self::State, (a0, a1): Self::Alphabet, _: usize) -> Self::State {
        s && a0 <= a1
    }
    fn accept(&self, s: Self::State) -> bool {
        s
    }
    fn unsuccessful(&self, s: Self::State) -> bool {
        !s
    }
}

fn count<X: Dfa>(dfa: &X, n: usize, modulo: u32, alphabet: &[X::Alphabet]) -> u32
where
    X::Alphabet: Copy,
    X::State: Eq + Hash + Copy,
{
    let mut dp = HashMap::new();
    let mut dp2 = HashMap::new();
    dp.insert(dfa.init(), 1_u64);
    for i in 0..n {
        for (s, k) in dp.drain() {
            let k = k % modulo as u64;
            for &a in alphabet {
                let s1 = dfa.next(s, a, i);
                if dfa.unsuccessful(s1) {
                    continue;
                }
                *dp2.entry(s1).or_insert(0) += k;
            }
        }
        std::mem::swap(&mut dp, &mut dp2);
    }
    let mut sum = 0;
    for (s, k) in dp {
        if dfa.accept(s) {
            sum += k;
            sum %= modulo as u64
        }
    }
    sum as u32
}


use proconio::input;

fn main() {
    input! {
        l: u64,
        r: u64,
    }
    let r = format!("{:b}", r).into_bytes();
    let l = format!("{:0width$b}", l, width = r.len()).into_bytes();

    let dfa = And(Prod(Not(Lt(&l)), Leq(&r)), And(SameMsb, Subset));
    let alphabet = [(b'0', b'0'), (b'0', b'1'), (b'1', b'0'), (b'1', b'1')];
    let ans = count(&dfa, r.len(), 1_000_000_007, &alphabet);
    println!("{}", ans);
}

Submission Info

Submission Time
Task F - Coincidence
User shino16
Language Rust (1.42.0)
Score 600
Code Size 6160 Byte
Status AC
Exec Time 7 ms
Memory 2188 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 600 / 600
Status
AC × 3
AC × 23
Set Name Test Cases
Sample a01, a02, a03
All a01, a02, a03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23
Case Name Status Exec Time Memory
a01 AC 7 ms 2028 KiB
a02 AC 2 ms 2076 KiB
a03 AC 4 ms 2164 KiB
b04 AC 1 ms 2048 KiB
b05 AC 2 ms 2044 KiB
b06 AC 2 ms 2056 KiB
b07 AC 2 ms 2120 KiB
b08 AC 2 ms 2088 KiB
b09 AC 2 ms 2092 KiB
b10 AC 3 ms 2040 KiB
b11 AC 2 ms 2060 KiB
b12 AC 2 ms 2056 KiB
b13 AC 2 ms 1984 KiB
b14 AC 2 ms 2052 KiB
b15 AC 2 ms 2124 KiB
b16 AC 2 ms 2188 KiB
b17 AC 2 ms 1992 KiB
b18 AC 3 ms 2080 KiB
b19 AC 2 ms 2084 KiB
b20 AC 2 ms 2060 KiB
b21 AC 2 ms 2104 KiB
b22 AC 1 ms 2020 KiB
b23 AC 2 ms 2044 KiB