QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#196495 | #7514. Clique Challenge | ucup-team296 | WA | 4ms | 3072kb | Rust | 35.3kb | 2023-10-01 18:19:01 | 2023-10-01 18:19:01 |
Judging History
answer
pub mod solution {
//{"name":"c","group":"Manual","url":"","interactive":false,"timeLimit":2000,"tests":[{"input":"","output":""},{"input":"","output":""}],"testType":"single","input":{"type":"stdin","fileName":null,"pattern":null},"output":{"type":"stdout","fileName":null,"pattern":null},"languages":{"java":{"taskClass":"c"}}}
use std::cmp::min;
use std::time::Instant;
use crate::algo_lib::collections::array_2d::Array2D;
use crate::algo_lib::io::output::output;
use crate::algo_lib::io::task_io_settings::TaskIoType;
use crate::algo_lib::io::task_runner::run_task;
use crate::algo_lib::io::input::Input;
use crate::algo_lib::io::task_io_settings::TaskIoSettings;
use crate::algo_lib::math::modulo::Mod7;
use crate::algo_lib::misc::gen_vector::gen_vec;
use crate::algo_lib::misc::rand::Random;
#[allow(unused)]
use crate::dbg;
use crate::out;
use crate::out_line;
type Mod = Mod7;
fn solve_g(g: &Array2D<bool>) -> Mod {
let n = g.len();
let mut deg: Vec<usize> = gen_vec(n, |id| (0..n).map(|to| if g[id][to] { 1 } else { 0 }).sum());
let mut seen = vec![false; n];
let mut res = Mod::ZERO;
for _ in 0..n {
let v = (0..n)
.filter(|&v| !seen[v])
.min_by_key(|&v| deg[v])
.unwrap();
seen[v] = true;
let mut neigh = vec![];
for to in 0..n {
if g[v][to] && !seen[to] {
deg[to] -= 1;
neigh.push(to);
}
}
assert!(neigh.len() <= 44);
let first_part = min((neigh.len() + 3) / 2, neigh.len());
let (first, second) = neigh.split_at(first_part);
let mut first_mask = vec![0; neigh.len()];
let mut second_mask = vec![0; neigh.len()];
for i in 0..neigh.len() {
let v = neigh[i];
for j in 0..first.len() {
if g[v][first[j]] {
first_mask[i] |= 1 << j;
}
}
for j in 0..second.len() {
if g[v][second[j]] {
second_mask[i] |= 1 << j;
}
}
}
let mut dp = vec![Mod::ZERO; 1 << second.len()];
let mut ok_first_mask = vec![(1 << first.len()) - 1; 1 << first.len()];
let mut ok_second_mask = vec![(1 << second.len()) - 1; 1 << first.len()];
for mask in 0usize..(1 << first.len()) {
if mask != 0 {
let first_bit = mask.trailing_zeros() as usize;
ok_first_mask[mask] &= first_mask[first_bit];
ok_second_mask[mask] &= second_mask[first_bit];
}
if mask & ok_first_mask[mask] != mask {
continue;
}
dp[ok_second_mask[mask]] += Mod::ONE;
}
for i in 0..second.len() {
for mask in 0..(1 << second.len()) {
if (1 << i) & mask != 0 {
let dp_mask = dp[mask];
dp[mask ^ (1 << i)] += dp_mask;
}
}
}
for mask in 0..(1 << second.len()) {
let mut ok_second_mask = (1 << second.len()) - 1;
for i in 0..second.len() {
if (1 << i) & mask != 0 {
ok_second_mask &= second_mask[i + first.len()];
}
}
if mask & ok_second_mask != mask {
continue;
}
res += dp[mask];
}
}
dbg!(res);
res
}
fn stress() {
for it in 1.. {
let start = Instant::now();
dbg!(it);
let mut rnd = Random::new(it);
let n = 45; //rnd.gen(1..2);
dbg!(n * (n - 1) / 2);
let mut m = rnd.gen(0..n * (n - 1) / 2 + 1);
if m > 1000 {
m = 1000;
}
let mut g = Array2D::new_f(n, n, |i, j| true);
for _ in 0..m {
let fr = rnd.gen(0..n);
let to = rnd.gen(0..n);
g[fr][to] = true;
g[to][fr] = true;
}
let res = solve_g(&g);
dbg!(start.elapsed());
}
}
fn solve(input: &mut Input, _test_case: usize) {
let n = input.usize();
let mut g = Array2D::new_f(n, n, |i, j| i == j);
let m = input.usize();
for _ in 0..m {
let fr = input.usize() - 1;
let to = input.usize() - 1;
g[fr][to] = true;
g[to][fr] = true;
}
let res = solve_g(&g);
out_line!(res);
}
pub(crate) fn run(mut input: Input) -> bool {
solve(&mut input, 1);
output().flush();
true
}
#[allow(unused)]
pub fn submit() -> bool {
let io = TaskIoSettings {
is_interactive: false,
input: TaskIoType::Std,
output: TaskIoType::Std,
};
run_task(io, run)
}
}
pub mod algo_lib {
pub mod collections {
pub mod array_2d {
use crate::algo_lib::io::output::Output;
use crate::algo_lib::io::output::Writable;
use crate::algo_lib::misc::num_traits::Number;
use std::io::Write;
use std::ops::Index;
use std::ops::IndexMut;
use std::ops::Mul;
// TODO: implement good Debug
#[derive(Clone, Debug)]
pub struct Array2D<T> {
rows: usize,
cols: usize,
v: Vec<T>,
}
pub struct Iter<'a, T> {
array: &'a Array2D<T>,
row: usize,
col: usize,
}
impl<T> Array2D<T>
where
T: Clone,
{
#[allow(unused)]
pub fn new(empty: T, rows: usize, cols: usize) -> Self {
Self {
rows,
cols,
v: vec![empty; rows * cols],
}
}
pub fn new_f(rows: usize, cols: usize, mut f: impl FnMut(usize, usize) -> T) -> Self {
let mut v = Vec::with_capacity(rows * cols);
for r in 0..rows {
for c in 0..cols {
v.push(f(r, c));
}
}
Self { rows, cols, v }
}
pub fn rows(&self) -> usize {
self.rows
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.rows()
}
pub fn cols(&self) -> usize {
self.cols
}
pub fn swap(&mut self, row1: usize, row2: usize) {
assert!(row1 < self.rows);
assert!(row2 < self.rows);
if row1 != row2 {
for col in 0..self.cols {
self.v.swap(row1 * self.cols + col, row2 * self.cols + col);
}
}
}
pub fn transpose(&self) -> Self {
Self::new_f(self.cols, self.rows, |r, c| self[c][r].clone())
}
pub fn iter(&self) -> Iter<T> {
Iter {
array: self,
row: 0,
col: 0,
}
}
pub fn pref_sum(&self) -> Self
where
T: Number,
{
let mut res = Self::new(T::ZERO, self.rows + 1, self.cols + 1);
for i in 0..self.rows {
for j in 0..self.cols {
let value = self[i][j] + res[i][j + 1] + res[i + 1][j] - res[i][j];
res[i + 1][j + 1] = value;
}
}
res
}
}
impl<T> Writable for Array2D<T>
where
T: Writable,
{
fn write(&self, output: &mut Output) {
for r in 0..self.rows {
self[r].write(output);
output.write_all(&[b'\n']).unwrap();
}
}
}
impl<T> Index<usize> for Array2D<T> {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
&self.v[(index) * self.cols..(index + 1) * self.cols]
}
}
impl<T> IndexMut<usize> for Array2D<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.v[(index) * self.cols..(index + 1) * self.cols]
}
}
impl<T> Mul for &Array2D<T>
where
T: Number,
{
type Output = Array2D<T>;
fn mul(self, rhs: Self) -> Self::Output {
let n = self.rows;
let m = self.cols;
assert_eq!(m, rhs.rows);
let k2 = rhs.cols;
let mut res = Array2D::new(T::ZERO, n, k2);
for i in 0..n {
for j in 0..m {
for k in 0..k2 {
res[i][k] += self[i][j] * rhs[j][k];
}
}
}
res
}
}
impl<T> Array2D<T>
where
T: Number,
{
pub fn pown(&self, pw: usize) -> Self {
assert_eq!(self.rows, self.cols);
let n = self.rows;
if pw == 0 {
Self::new_f(n, n, |r, c| if r == c { T::ONE } else { T::ZERO })
} else if pw == 1 {
self.clone()
} else {
let half = self.pown(pw / 2);
let half2 = &half * ½
if pw & 1 == 0 {
half2
} else {
&half2 * self
}
}
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.col == self.array.cols {
self.col = 0;
self.row += 1;
}
if self.row >= self.array.rows {
return None;
}
let elem = &self.array[self.row][self.col];
self.col += 1;
Some(elem)
}
}
}
pub mod last_exn {
use std::collections::BTreeSet;
pub trait LastExn<T> {
fn last_exn(&self) -> &T;
}
impl<T> LastExn<T> for &[T] {
fn last_exn(&self) -> &T {
self.last().unwrap()
}
}
impl<T> LastExn<T> for Vec<T> {
fn last_exn(&self) -> &T {
self.last().unwrap()
}
}
impl<T> LastExn<T> for BTreeSet<T> {
fn last_exn(&self) -> &T {
self.iter().next_back().unwrap()
}
}
}
}
pub mod io {
pub mod input {
use std::fmt::Debug;
use std::io::Read;
use std::marker::PhantomData;
use std::path::Path;
use std::str::FromStr;
pub struct Input {
input: Box<dyn Read>,
buf: Vec<u8>,
at: usize,
buf_read: usize,
}
macro_rules! read_integer_fun {
($t:ident) => {
#[allow(unused)]
pub fn $t(&mut self) -> $t {
self.read_integer()
}
};
}
impl Input {
const DEFAULT_BUF_SIZE: usize = 4096;
///
/// Using with stdin:
/// ```no_run
/// use algo_lib::io::input::Input;
/// let stdin = std::io::stdin();
/// let input = Input::new(Box::new(stdin));
/// ```
///
/// For read files use ``new_file`` instead.
///
///
pub fn new(input: Box<dyn Read>) -> Self {
Self {
input,
buf: vec![0; Self::DEFAULT_BUF_SIZE],
at: 0,
buf_read: 0,
}
}
pub fn new_file<P: AsRef<Path>>(path: P) -> Self {
let file = std::fs::File::open(&path)
.unwrap_or_else(|_| panic!("Can't open file: {:?}", path.as_ref().as_os_str()));
Self::new(Box::new(file))
}
pub fn new_with_size(input: Box<dyn Read>, buf_size: usize) -> Self {
Self {
input,
buf: vec![0; buf_size],
at: 0,
buf_read: 0,
}
}
pub fn new_file_with_size<P: AsRef<Path>>(path: P, buf_size: usize) -> Self {
let file = std::fs::File::open(&path)
.unwrap_or_else(|_| panic!("Can't open file: {:?}", path.as_ref().as_os_str()));
Self::new_with_size(Box::new(file), buf_size)
}
pub fn get(&mut self) -> Option<u8> {
if self.refill_buffer() {
let res = self.buf[self.at];
self.at += 1;
Some(res)
} else {
None
}
}
pub fn peek(&mut self) -> Option<u8> {
if self.refill_buffer() {
Some(self.buf[self.at])
} else {
None
}
}
pub fn skip_whitespace(&mut self) {
while let Some(b) = self.peek() {
if !char::from(b).is_whitespace() {
return;
}
self.get();
}
}
pub fn next_token(&mut self) -> Option<Vec<u8>> {
self.skip_whitespace();
let mut res = Vec::new();
while let Some(c) = self.get() {
if char::from(c).is_whitespace() {
break;
}
res.push(c);
}
if res.is_empty() {
None
} else {
Some(res)
}
}
//noinspection RsSelfConvention
pub fn is_exhausted(&mut self) -> bool {
self.peek().is_none()
}
pub fn has_more_elements(&mut self) -> bool {
!self.is_exhausted()
}
pub fn read<T: Readable>(&mut self) -> T {
T::read(self)
}
pub fn vec<T: Readable>(&mut self, size: usize) -> Vec<T> {
let mut res = Vec::with_capacity(size);
for _ in 0usize..size {
res.push(self.read());
}
res
}
pub fn string_vec(&mut self, size: usize) -> Vec<Vec<u8>> {
let mut res = Vec::with_capacity(size);
for _ in 0usize..size {
res.push(self.string());
}
res
}
pub fn read_line(&mut self) -> String {
let mut res = String::new();
while let Some(c) = self.get() {
if c == b'\n' {
break;
}
if c == b'\r' {
if self.peek() == Some(b'\n') {
self.get();
}
break;
}
res.push(c.into());
}
res
}
#[allow(clippy::should_implement_trait)]
pub fn into_iter<T: Readable>(self) -> InputIterator<T> {
InputIterator {
input: self,
phantom: Default::default(),
}
}
fn read_integer<T: FromStr>(&mut self) -> T
where
<T as FromStr>::Err: Debug,
{
let res = self.read_string();
res.parse::<T>().unwrap()
}
fn read_string(&mut self) -> String {
match self.next_token() {
None => {
panic!("Input exhausted");
}
Some(res) => unsafe { String::from_utf8_unchecked(res) },
}
}
pub fn string_as_string(&mut self) -> String {
self.read_string()
}
pub fn string(&mut self) -> Vec<u8> {
self.read_string().into_bytes()
}
fn read_char(&mut self) -> char {
self.skip_whitespace();
self.get().unwrap().into()
}
fn read_float(&mut self) -> f64 {
self.read_string().parse().unwrap()
}
pub fn f64(&mut self) -> f64 {
self.read_float()
}
fn refill_buffer(&mut self) -> bool {
if self.at == self.buf_read {
self.at = 0;
self.buf_read = self.input.read(&mut self.buf).unwrap();
self.buf_read != 0
} else {
true
}
}
read_integer_fun!(i32);
read_integer_fun!(i64);
read_integer_fun!(i128);
read_integer_fun!(u32);
read_integer_fun!(u64);
read_integer_fun!(usize);
}
pub trait Readable {
fn read(input: &mut Input) -> Self;
}
impl Readable for String {
fn read(input: &mut Input) -> Self {
input.read_string()
}
}
impl Readable for char {
fn read(input: &mut Input) -> Self {
input.read_char()
}
}
impl Readable for f64 {
fn read(input: &mut Input) -> Self {
input.read_string().parse().unwrap()
}
}
impl Readable for f32 {
fn read(input: &mut Input) -> Self {
input.read_string().parse().unwrap()
}
}
impl<T: Readable> Readable for Vec<T> {
fn read(input: &mut Input) -> Self {
let size = input.read();
input.vec(size)
}
}
pub struct InputIterator<T: Readable> {
input: Input,
phantom: PhantomData<T>,
}
impl<T: Readable> Iterator for InputIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.input.skip_whitespace();
self.input.peek().map(|_| self.input.read())
}
}
macro_rules! read_integer {
($t:ident) => {
impl Readable for $t {
fn read(input: &mut Input) -> Self {
input.read_integer()
}
}
};
}
read_integer!(i8);
read_integer!(i16);
read_integer!(i32);
read_integer!(i64);
read_integer!(i128);
read_integer!(isize);
read_integer!(u8);
read_integer!(u16);
read_integer!(u32);
read_integer!(u64);
read_integer!(u128);
read_integer!(usize);
}
pub mod output {
use std::io::Write;
pub struct Output {
output: Box<dyn Write>,
buf: Vec<u8>,
at: usize,
auto_flush: bool,
}
impl Output {
const DEFAULT_BUF_SIZE: usize = 4096;
pub fn new(output: Box<dyn Write>) -> Self {
Self {
output,
buf: vec![0; Self::DEFAULT_BUF_SIZE],
at: 0,
auto_flush: false,
}
}
pub fn new_with_auto_flush(output: Box<dyn Write>) -> Self {
Self {
output,
buf: vec![0; Self::DEFAULT_BUF_SIZE],
at: 0,
auto_flush: true,
}
}
pub fn flush(&mut self) {
if self.at != 0 {
self.output.write_all(&self.buf[..self.at]).unwrap();
self.at = 0;
self.output.flush().expect("Couldn't flush output");
}
}
pub fn print<T: Writable>(&mut self, s: &T) {
s.write(self);
}
pub fn put(&mut self, b: u8) {
self.buf[self.at] = b;
self.at += 1;
if self.at == self.buf.len() {
self.flush();
}
}
pub fn maybe_flush(&mut self) {
if self.auto_flush {
self.flush();
}
}
pub fn print_per_line<T: Writable>(&mut self, arg: &[T]) {
for i in arg {
i.write(self);
self.put(b'\n');
}
}
pub fn print_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
let mut first = true;
for e in iter {
if first {
first = false;
} else {
self.put(b' ');
}
e.write(self);
}
}
pub fn print_iter_ref<'a, T: 'a + Writable, I: Iterator<Item = &'a T>>(&mut self, iter: I) {
let mut first = true;
for e in iter {
if first {
first = false;
} else {
self.put(b' ');
}
e.write(self);
}
}
}
impl Write for Output {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut start = 0usize;
let mut rem = buf.len();
while rem > 0 {
let len = (self.buf.len() - self.at).min(rem);
self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
self.at += len;
if self.at == self.buf.len() {
self.flush();
}
start += len;
rem -= len;
}
if self.auto_flush {
self.flush();
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
self.flush();
Ok(())
}
}
pub trait Writable {
fn write(&self, output: &mut Output);
}
impl Writable for &str {
fn write(&self, output: &mut Output) {
output.write_all(self.as_bytes()).unwrap();
}
}
impl Writable for String {
fn write(&self, output: &mut Output) {
output.write_all(self.as_bytes()).unwrap();
}
}
impl Writable for char {
fn write(&self, output: &mut Output) {
output.put(*self as u8);
}
}
impl<T: Writable> Writable for [T] {
fn write(&self, output: &mut Output) {
output.print_iter_ref(self.iter());
}
}
impl<T: Writable> Writable for Vec<T> {
fn write(&self, output: &mut Output) {
self[..].write(output);
}
}
macro_rules! write_to_string {
($t:ident) => {
impl Writable for $t {
fn write(&self, output: &mut Output) {
self.to_string().write(output);
}
}
};
}
write_to_string!(u8);
write_to_string!(u16);
write_to_string!(u32);
write_to_string!(u64);
write_to_string!(u128);
write_to_string!(usize);
write_to_string!(i8);
write_to_string!(i16);
write_to_string!(i32);
write_to_string!(i64);
write_to_string!(i128);
write_to_string!(isize);
write_to_string!(f32);
write_to_string!(f64);
impl<T: Writable, U: Writable> Writable for (T, U) {
fn write(&self, output: &mut Output) {
self.0.write(output);
output.put(b' ');
self.1.write(output);
}
}
impl<T: Writable, U: Writable, V: Writable> Writable for (T, U, V) {
fn write(&self, output: &mut Output) {
self.0.write(output);
output.put(b' ');
self.1.write(output);
output.put(b' ');
self.2.write(output);
}
}
pub static mut OUTPUT: Option<Output> = None;
pub fn set_global_output_to_stdout() {
unsafe {
OUTPUT = Some(Output::new(Box::new(std::io::stdout())));
}
}
pub fn set_global_output_to_file(path: &str) {
unsafe {
let out_file =
std::fs::File::create(path).unwrap_or_else(|_| panic!("Can't create file {}", path));
OUTPUT = Some(Output::new(Box::new(out_file)));
}
}
pub fn set_global_output_to_none() {
unsafe {
match &mut OUTPUT {
None => {}
Some(output) => output.flush(),
}
OUTPUT = None;
}
}
pub fn output() -> &'static mut Output {
unsafe {
match &mut OUTPUT {
None => {
panic!("Global output wasn't initialized");
}
Some(output) => output,
}
}
}
#[macro_export]
macro_rules! out {
($first: expr $(,$args:expr )*) => {
output().print(&$first);
$(output().put(b' ');
output().print(&$args);
)*
output().maybe_flush();
}
}
#[macro_export]
macro_rules! out_line {
($first: expr $(, $args:expr )* ) => {
{
out!($first $(,$args)*);
output().put(b'\n');
output().maybe_flush();
}
};
() => {
{
output().put(b'\n');
output().maybe_flush();
}
};
}
}
pub mod task_io_settings {
pub enum TaskIoType {
Std,
File(String),
}
pub struct TaskIoSettings {
pub is_interactive: bool,
pub input: TaskIoType,
pub output: TaskIoType,
}
}
pub mod task_runner {
use std::io::Write;
use super::input::Input;
use super::output::Output;
use super::output::OUTPUT;
use super::task_io_settings::TaskIoSettings;
use super::task_io_settings::TaskIoType;
pub fn run_task<Res>(io: TaskIoSettings, run: impl FnOnce(Input) -> Res) -> Res {
let output: Box<dyn Write> = match io.output {
TaskIoType::Std => Box::new(std::io::stdout()),
TaskIoType::File(file) => {
let out_file = std::fs::File::create(file).unwrap();
Box::new(out_file)
}
};
unsafe {
OUTPUT = Some(Output::new(output));
}
let input = match io.input {
TaskIoType::Std => {
let sin = std::io::stdin();
Input::new(Box::new(sin))
}
TaskIoType::File(file) => Input::new_file(file),
};
run(input)
}
}
}
pub mod math {
pub mod modulo {
use crate::algo_lib::collections::last_exn::LastExn;
use crate::algo_lib::io::input::Input;
use crate::algo_lib::io::input::Readable;
use crate::algo_lib::io::output::Output;
use crate::algo_lib::io::output::Writable;
use crate::algo_lib::misc::num_traits::ConvSimple;
use crate::algo_lib::misc::num_traits::HasConstants;
use crate::algo_lib::misc::num_traits::Number;
use std::io::Write;
use std::marker::PhantomData;
pub trait Value: Clone + Copy + Eq + Default + Ord {
fn val() -> i32;
}
#[derive(Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd, Hash)]
pub struct ModWithValue<M>(i32, PhantomData<M>)
where
M: Value;
impl<M> ModWithValue<M>
where
M: Value,
{
#[allow(unused)]
pub const ZERO: Self = Self(0, PhantomData);
#[allow(unused)]
pub const ONE: Self = Self(1, PhantomData);
#[allow(unused)]
pub const TWO: Self = Self(2, PhantomData);
fn rev_rec(a: i32, m: i32) -> i32 {
if a == 1 {
return a;
}
((1 - Self::rev_rec(m % a, a) as i64 * m as i64) / a as i64 + m as i64) as i32
}
#[allow(dead_code)]
pub fn inv(self) -> Self {
ModWithValue(Self::rev_rec(self.0, M::val()), PhantomData)
}
pub fn value(&self) -> i32 {
self.0
}
#[allow(dead_code)]
pub fn new<T: Number>(x: T) -> Self {
let mut x = x.to_i32();
if x < 0 {
x += M::val();
if x < 0 {
x %= M::val();
x += M::val();
}
} else if x >= M::val() {
x -= M::val();
if x >= M::val() {
x %= M::val();
}
}
assert!(0 <= x && x < M::val());
Self(x, PhantomData)
}
pub fn pown(self, pw: usize) -> Self {
if pw == 0 {
Self::ONE
} else if pw == 1 {
self
} else {
let half = self.pown(pw / 2);
let res = half * half;
if pw % 2 == 0 {
res
} else {
res * self
}
}
}
pub fn gen_powers(base: Self, n: usize) -> Vec<Self> {
let mut res = Vec::with_capacity(n);
res.push(Self::ONE);
for _ in 1..n {
res.push(*res.last_exn() * base);
}
res
}
}
impl<M> std::fmt::Display for ModWithValue<M>
where
M: Value,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<M> std::fmt::Debug for ModWithValue<M>
where
M: Value + Copy + Eq,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
const MAX: i32 = 100;
if self.0 <= MAX {
write!(f, "{}", self.0)
} else if self.0 >= M::val() - MAX {
write!(f, "-{}", M::val() - self.0)
} else {
for denom in 1..MAX {
let num = *self * Self(denom, PhantomData);
if num.0 <= MAX {
return write!(f, "{}/{}", num.0, denom);
} else if num.0 >= M::val() - MAX {
return write!(f, "-{}/{}", M::val() - num.0, denom);
}
}
write!(f, "(?? {} ??)", self.0)
}
}
}
impl<M> std::ops::Add for ModWithValue<M>
where
M: Value,
{
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
let res = self.0 + rhs.0;
if res >= M::val() {
ModWithValue(res - M::val(), PhantomData)
} else {
ModWithValue(res, PhantomData)
}
}
}
impl<M> std::ops::AddAssign for ModWithValue<M>
where
M: Value,
{
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
if self.0 >= M::val() {
self.0 -= M::val();
}
}
}
impl<M> std::ops::Sub for ModWithValue<M>
where
M: Value,
{
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
let res = self.0 - rhs.0;
if res < 0 {
ModWithValue(res + M::val(), PhantomData)
} else {
ModWithValue(res, PhantomData)
}
}
}
impl<M> std::ops::SubAssign for ModWithValue<M>
where
M: Value,
{
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
if self.0 < 0 {
self.0 += M::val();
}
}
}
impl<M> std::ops::Mul for ModWithValue<M>
where
M: Value,
{
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
let res = (self.0 as i64) * (rhs.0 as i64) % (M::val() as i64);
ModWithValue(res as i32, PhantomData)
}
}
impl<M> std::ops::MulAssign for ModWithValue<M>
where
M: Value,
{
fn mul_assign(&mut self, rhs: Self) {
self.0 = ((self.0 as i64) * (rhs.0 as i64) % (M::val() as i64)) as i32;
}
}
impl<M> std::ops::Div for ModWithValue<M>
where
M: Value,
{
type Output = Self;
#[allow(clippy::suspicious_arithmetic_impl)]
fn div(self, rhs: Self) -> Self::Output {
let rhs_inv = rhs.inv();
self * rhs_inv
}
}
impl<M> std::ops::DivAssign for ModWithValue<M>
where
M: Value,
{
#[allow(clippy::suspicious_op_assign_impl)]
fn div_assign(&mut self, rhs: Self) {
*self *= rhs.inv();
}
}
impl<M> Writable for ModWithValue<M>
where
M: Value,
{
fn write(&self, output: &mut Output) {
output.write_fmt(format_args!("{}", self.0)).unwrap();
}
}
impl<M> Readable for ModWithValue<M>
where
M: Value,
{
fn read(input: &mut Input) -> Self {
let i32 = input.i32();
Self::new(i32)
}
}
impl<M> HasConstants<ModWithValue<M>> for ModWithValue<M>
where
M: Value,
{
// This doesn't make much sense, but hope we never use
const MAX: ModWithValue<M> = ModWithValue::ZERO;
const MIN: ModWithValue<M> = ModWithValue::ZERO;
const ZERO: ModWithValue<M> = ModWithValue::ZERO;
const ONE: ModWithValue<M> = ModWithValue::ONE;
const TWO: ModWithValue<M> = ModWithValue::TWO;
}
impl<M> ConvSimple<ModWithValue<M>> for ModWithValue<M>
where
M: Value,
{
fn from_i32(val: i32) -> ModWithValue<M> {
ModWithValue::new(val)
}
fn to_i32(self) -> i32 {
self.0
}
fn to_f64(self) -> f64 {
self.0 as f64
}
}
pub trait ConstValue: Value + Copy {
const VAL: i32;
}
impl<V: ConstValue> Value for V {
fn val() -> i32 {
Self::VAL
}
}
#[derive(Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd, Hash)]
pub struct Value7();
impl ConstValue for Value7 {
const VAL: i32 = 1_000_000_007;
}
pub type Mod7 = ModWithValue<Value7>;
#[derive(Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd, Hash)]
pub struct Value9();
impl ConstValue for Value9 {
const VAL: i32 = 1_000_000_009;
}
pub type Mod9 = ModWithValue<Value9>;
#[derive(Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd, Hash)]
#[allow(non_camel_case_types)]
pub struct Value_998_244_353();
impl ConstValue for Value_998_244_353 {
const VAL: i32 = 998_244_353;
}
#[allow(non_camel_case_types)]
pub type Mod_998_244_353 = ModWithValue<Value_998_244_353>;
pub trait ModuloTrait: Number {
fn mod_value() -> i32;
fn pown(self, n: usize) -> Self;
}
impl<V: Value> ModuloTrait for ModWithValue<V> {
fn mod_value() -> i32 {
V::val()
}
fn pown(self, n: usize) -> Self {
self.pown(n)
}
}
}
}
pub mod misc {
pub mod dbg_macro {
#[macro_export]
#[allow(unused_macros)]
macro_rules! dbg {
($first_val:expr, $($val:expr),+ $(,)?) => {
eprint!("[{}:{}] {} = {:?}",
file!(), line!(), stringify!($first_val), &$first_val);
($(eprint!(", {} = {:?}", stringify!($val), &$val)),+,);
eprintln!();
};
($first_val:expr) => {
eprintln!("[{}:{}] {} = {:?}",
file!(), line!(), stringify!($first_val), &$first_val)
};
}
}
pub mod gen_vector {
pub fn gen_vec<T>(n: usize, f: impl FnMut(usize) -> T) -> Vec<T> {
(0..n).map(f).collect()
}
}
pub mod num_traits {
use std::cmp::Ordering;
use std::fmt::Debug;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Div;
use std::ops::DivAssign;
use std::ops::Mul;
use std::ops::MulAssign;
use std::ops::Sub;
use std::ops::SubAssign;
pub trait HasConstants<T> {
const MAX: T;
const MIN: T;
const ZERO: T;
const ONE: T;
const TWO: T;
}
pub trait ConvSimple<T> {
fn from_i32(val: i32) -> T;
fn to_i32(self) -> i32;
fn to_f64(self) -> f64;
}
pub trait Signum {
fn signum(&self) -> i32;
}
pub trait Number:
Copy
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Mul<Output = Self>
+ MulAssign
+ Div<Output = Self>
+ DivAssign
+ PartialOrd
+ PartialEq
+ HasConstants<Self>
+ Default
+ Debug
+ Sized
+ ConvSimple<Self>
{
}
impl<
T: Copy
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Mul<Output = Self>
+ MulAssign
+ Div<Output = Self>
+ DivAssign
+ PartialOrd
+ PartialEq
+ HasConstants<Self>
+ Default
+ Debug
+ Sized
+ ConvSimple<Self>,
> Number for T
{
}
macro_rules! has_constants_impl {
($t: ident) => {
impl HasConstants<$t> for $t {
// TODO: remove `std` for new rust version..
const MAX: $t = std::$t::MAX;
const MIN: $t = std::$t::MIN;
const ZERO: $t = 0;
const ONE: $t = 1;
const TWO: $t = 2;
}
impl ConvSimple<$t> for $t {
fn from_i32(val: i32) -> $t {
val as $t
}
fn to_i32(self) -> i32 {
self as i32
}
fn to_f64(self) -> f64 {
self as f64
}
}
};
}
has_constants_impl!(i32);
has_constants_impl!(i64);
has_constants_impl!(i128);
has_constants_impl!(u32);
has_constants_impl!(u64);
has_constants_impl!(u128);
has_constants_impl!(usize);
has_constants_impl!(u8);
impl ConvSimple<Self> for f64 {
fn from_i32(val: i32) -> Self {
val as f64
}
fn to_i32(self) -> i32 {
self as i32
}
fn to_f64(self) -> f64 {
self
}
}
impl HasConstants<Self> for f64 {
const MAX: Self = Self::MAX;
const MIN: Self = -Self::MAX;
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
const TWO: Self = 2.0;
}
impl<T: Number + Ord> Signum for T {
fn signum(&self) -> i32 {
match self.cmp(&T::ZERO) {
Ordering::Greater => 1,
Ordering::Less => -1,
Ordering::Equal => 0,
}
}
}
}
pub mod rand {
use crate::algo_lib::misc::gen_vector::gen_vec;
use crate::algo_lib::misc::num_traits::Number;
use std::ops::Range;
use std::time::SystemTime;
use std::time::UNIX_EPOCH;
#[allow(dead_code)]
pub struct Random {
state: u64,
}
impl Random {
pub fn gen_u64(&mut self) -> u64 {
let mut x = self.state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.state = x;
x
}
#[allow(dead_code)]
pub fn next_in_range(&mut self, from: usize, to: usize) -> usize {
assert!(from < to);
(from as u64 + self.gen_u64() % ((to - from) as u64)) as usize
}
pub fn gen_index<T>(&mut self, a: &[T]) -> usize {
self.gen(0..a.len())
}
#[allow(dead_code)]
#[inline(always)]
pub fn gen_double(&mut self) -> f64 {
(self.gen_u64() as f64) / (std::usize::MAX as f64)
}
#[allow(dead_code)]
pub fn new(seed: u64) -> Self {
let state = if seed == 0 { 787788 } else { seed };
Self { state }
}
pub fn new_time_seed() -> Self {
let time = SystemTime::now();
let seed = (time.duration_since(UNIX_EPOCH).unwrap().as_nanos() % 1_000_000_000) as u64;
if seed == 0 {
Self::new(787788)
} else {
Self::new(seed)
}
}
#[allow(dead_code)]
pub fn gen_permutation(&mut self, n: usize) -> Vec<usize> {
let mut result: Vec<_> = (0..n).collect();
for i in 0..n {
let idx = self.next_in_range(0, i + 1);
result.swap(i, idx);
}
result
}
pub fn shuffle<T>(&mut self, a: &mut [T]) {
for i in 1..a.len() {
a.swap(i, self.gen(0..i + 1));
}
}
pub fn gen<T>(&mut self, range: Range<T>) -> T
where
T: Number,
{
let from = T::to_i32(range.start);
let to = T::to_i32(range.end);
assert!(from < to);
let len = (to - from) as usize;
T::from_i32(self.next_in_range(0, len) as i32 + from)
}
pub fn gen_vec<T>(&mut self, n: usize, range: Range<T>) -> Vec<T>
where
T: Number,
{
gen_vec(n, |_| self.gen(range.clone()))
}
pub fn gen_nonempty_range(&mut self, n: usize) -> Range<usize> {
let x = self.gen(0..n);
let y = self.gen(0..n);
if x <= y {
x..y + 1
} else {
y..x + 1
}
}
pub fn gen_bool(&mut self) -> bool {
self.gen(0..2) == 0
}
}
}
}
}
fn main() {
crate::solution::submit();
}
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 2020kb
input:
3 2 1 2 2 3
output:
5
result:
ok single line: '5'
Test #2:
score: 0
Accepted
time: 0ms
memory: 2016kb
input:
3 3 1 2 1 3 2 3
output:
7
result:
ok single line: '7'
Test #3:
score: -100
Wrong Answer
time: 4ms
memory: 3072kb
input:
1000 100 446 789 167 547 254 777 777 185 33 446 777 847 185 877 757 167 72 383 847 446 254 478 959 185 757 446 847 959 959 167 757 847 747 757 446 167 989 757 547 777 33 747 33 254 254 843 33 547 446 980 877 205 185 72 980 959 33 205 877 757 33 847 478 843 757 478 167 877 72 789 877 959 980 478 167 ...
output:
1495
result:
wrong answer 1st lines differ - expected: '1373', found: '1495'