QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#730494 | #9572. Bingo | ucup-team296# | AC ✓ | 205ms | 12540kb | Rust | 47.7kb | 2024-11-09 20:27:02 | 2024-11-09 20:27:02 |
Judging History
answer
// https://contest.ucup.ac/contest/1828/problem/9572
pub mod solution {
//{"name":"I. Bingo","group":"Universal Cup - The 3rd Universal Cup. Stage 16: Nanjing","url":"https://contest.ucup.ac/contest/1828/problem/9572","interactive":false,"timeLimit":1000,"tests":[{"input":"4\n2 2\n1 3 2 4\n3 1\n10 10 10\n1 3\n20 10 30\n3 4\n1 1 4 5 1 4 1 9 1 9 8 10\n","output":"56\n60\n60\n855346687\n"}],"testType":"single","input":{"type":"stdin","fileName":null,"pattern":null},"output":{"type":"stdout","fileName":null,"pattern":null},"languages":{"java":{"taskClass":"IBingo"}}}
use crate::algo_lib::collections::vec_ext::sorted::Sorted;
use crate::algo_lib::io::input::Input;
use crate::algo_lib::io::output::Output;
use crate::algo_lib::misc::test_type::TaskType;
use crate::algo_lib::misc::test_type::TestType;
use crate::algo_lib::numbers::mod_int::ModIntF;
use crate::algo_lib::numbers::mod_utils::Combinations;
use crate::algo_lib::numbers::num_traits::algebra::One;
use crate::algo_lib::numbers::num_traits::algebra::Zero;
use crate::algo_lib::numbers::prime_fft::PrimeFFT;
type PreCalc = ();
fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
let n = input.read_size();
let m = input.read_size();
let a = input.read_int_vec(n * m).sorted();
type Mod = ModIntF;
let c = Combinations::<Mod>::new(n * m + 1);
let mut v = vec![Mod::zero(); n * m + 1];
for i in 0..=n {
for j in 0..=m {
if i + j == 0 {
continue;
}
v[i * m + j * n - i * j] += if (i + j) % 2 == 0 {
Mod::new(-1)
} else {
Mod::one()
} * c.c(n, i)
* c.c(m, j);
}
}
let mut u = vec![Mod::zero(); n * m + 1];
for i in 0..=n * m {
v[i] *= c.fact(n * m - i);
u[i] = c.inv_fact(i);
}
let res = PrimeFFT::new().multiply(&v, &u);
let mut so_far = Mod::zero();
let mut ans = Mod::zero();
for i in 1..=n * m {
if i != n * m && a[i] == a[i - 1] {
continue;
}
let cur = res[i] * c.fact(i);
ans += (cur - so_far) * Mod::new(a[i - 1]);
so_far = cur;
}
out.print_line(ans);
}
pub static TEST_TYPE: TestType = TestType::MultiNumber;
pub static TASK_TYPE: TaskType = TaskType::Classic;
pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
let mut pre_calc = ();
match TEST_TYPE {
TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
TestType::MultiNumber => {
let t = input.read();
for i in 1..=t {
solve(&mut input, &mut output, i, &mut pre_calc);
}
}
TestType::MultiEof => {
let mut i = 1;
while input.peek().is_some() {
solve(&mut input, &mut output, i, &mut pre_calc);
i += 1;
}
}
}
output.flush();
match TASK_TYPE {
TaskType::Classic => input.is_empty(),
TaskType::Interactive => true,
}
}
}
pub mod algo_lib {
pub mod collections {
pub mod fx_hash_map {
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cell::Cell;
use std::convert::TryInto;
use std::time::SystemTime;
use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::BuildHasherDefault;
use std::hash::Hasher;
use std::mem::size_of;
use std::ops::BitXor;
pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub type FxHashSet<V> = HashSet<V, BuildHasherDefault<FxHasher>>;
#[derive(Default)]
pub struct FxHasher {
hash: usize,
}
thread_local! {
static K: Cell<usize> = Cell::new(
((SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos().wrapping_mul(2) + 1) & 0xFFFFFFFFFFFFFFFF) as usize
);
}
impl FxHasher {
#[inline]
fn add_to_hash(&mut self, i: usize) {
self.hash = self
.hash
.rotate_left(5)
.bitxor(i)
.wrapping_mul(K.with(|k| k.get()));
}
}
impl Hasher for FxHasher {
#[inline]
fn write(&mut self, mut bytes: &[u8]) {
let read_usize = |bytes: &[u8]| u64::from_ne_bytes(bytes[..8].try_into().unwrap());
let mut hash = FxHasher { hash: self.hash };
while bytes.len() >= size_of::<usize>() {
hash.add_to_hash(read_usize(bytes) as usize);
bytes = &bytes[size_of::<usize>()..];
}
if (size_of::<usize>() > 4) && (bytes.len() >= 4) {
hash.add_to_hash(u32::from_ne_bytes(bytes[..4].try_into().unwrap()) as usize);
bytes = &bytes[4..];
}
if (size_of::<usize>() > 2) && bytes.len() >= 2 {
hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize);
bytes = &bytes[2..];
}
if (size_of::<usize>() > 1) && !bytes.is_empty() {
hash.add_to_hash(bytes[0] as usize);
}
self.hash = hash.hash;
}
#[inline]
fn write_u8(&mut self, i: u8) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u16(&mut self, i: u16) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u64(&mut self, i: u64) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.add_to_hash(i);
}
#[inline]
fn finish(&self) -> u64 {
self.hash as u64
}
}
}
pub mod slice_ext {
pub mod legacy_fill {
// 1.50
pub trait LegacyFill<T> {
fn legacy_fill(&mut self, val: T);
}
impl<T: Clone> LegacyFill<T> for [T] {
fn legacy_fill(&mut self, val: T) {
for el in self.iter_mut() {
*el = val.clone();
}
}
}
}
}
pub mod vec_ext {
pub mod default {
pub fn default_vec<T: Default>(len: usize) -> Vec<T> {
let mut v = Vec::with_capacity(len);
for _ in 0..len {
v.push(T::default());
}
v
}
}
pub mod sorted {
pub trait Sorted {
fn sorted(self) -> Self;
}
impl<T: Ord> Sorted for Vec<T> {
fn sorted(mut self) -> Self {
self.sort();
self
}
}
}
}
}
pub mod io {
pub mod input {
use crate::algo_lib::collections::vec_ext::default::default_vec;
use std::io::Read;
pub struct Input<'s> {
input: &'s mut (dyn Read + Send),
buf: Vec<u8>,
at: usize,
buf_read: usize,
}
macro_rules! read_impl {
($t: ty, $read_name: ident, $read_vec_name: ident) => {
pub fn $read_name(&mut self) -> $t {
self.read()
}
pub fn $read_vec_name(&mut self, len: usize) -> Vec<$t> {
self.read_vec(len)
}
};
($t: ty, $read_name: ident, $read_vec_name: ident, $read_pair_vec_name: ident) => {
read_impl!($t, $read_name, $read_vec_name);
pub fn $read_pair_vec_name(&mut self, len: usize) -> Vec<($t, $t)> {
self.read_vec(len)
}
};
}
impl<'s> Input<'s> {
const DEFAULT_BUF_SIZE: usize = 4096;
pub fn new(input: &'s mut (dyn Read + Send)) -> Self {
Self {
input,
buf: default_vec(Self::DEFAULT_BUF_SIZE),
at: 0,
buf_read: 0,
}
}
pub fn new_with_size(input: &'s mut (dyn Read + Send), buf_size: usize) -> Self {
Self {
input,
buf: default_vec(buf_size),
at: 0,
buf_read: 0,
}
}
pub fn get(&mut self) -> Option<u8> {
if self.refill_buffer() {
let res = self.buf[self.at];
self.at += 1;
if res == b'\r' {
if self.refill_buffer() && self.buf[self.at] == b'\n' {
self.at += 1;
}
return Some(b'\n');
}
Some(res)
} else {
None
}
}
pub fn peek(&mut self) -> Option<u8> {
if self.refill_buffer() {
let res = self.buf[self.at];
Some(if res == b'\r' { b'\n' } else { res })
} else {
None
}
}
pub fn skip_whitespace(&mut self) {
while let Some(b) = self.peek() {
if !b.is_ascii_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 c.is_ascii_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()
}
//noinspection RsSelfConvention
pub fn is_empty(&mut self) -> bool {
self.skip_whitespace();
self.is_exhausted()
}
pub fn read<T: Readable>(&mut self) -> T {
T::read(self)
}
pub fn read_vec<T: Readable>(&mut self, size: usize) -> Vec<T> {
let mut res = Vec::with_capacity(size);
for _ in 0..size {
res.push(self.read());
}
res
}
pub fn read_char(&mut self) -> u8 {
self.skip_whitespace();
self.get().unwrap()
}
read_impl!(u32, read_unsigned, read_unsigned_vec);
read_impl!(u64, read_u64, read_u64_vec);
read_impl!(usize, read_size, read_size_vec, read_size_pair_vec);
read_impl!(i32, read_int, read_int_vec, read_int_pair_vec);
read_impl!(i64, read_long, read_long_vec, read_long_pair_vec);
read_impl!(i128, read_i128, read_i128_vec);
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
}
}
}
pub trait Readable {
fn read(input: &mut Input) -> Self;
}
impl Readable for u8 {
fn read(input: &mut Input) -> Self {
input.read_char()
}
}
impl<T: Readable> Readable for Vec<T> {
fn read(input: &mut Input) -> Self {
let size = input.read();
input.read_vec(size)
}
}
macro_rules! read_integer {
($($t:ident)+) => {$(
impl Readable for $t {
fn read(input: &mut Input) -> Self {
input.skip_whitespace();
let mut c = input.get().unwrap();
let sgn = match c {
b'-' => {
c = input.get().unwrap();
true
}
b'+' => {
c = input.get().unwrap();
false
}
_ => false,
};
let mut res = 0;
loop {
assert!(c.is_ascii_digit());
res *= 10;
let d = (c - b'0') as $t;
if sgn {
res -= d;
} else {
res += d;
}
match input.get() {
None => break,
Some(ch) => {
if ch.is_ascii_whitespace() {
break;
} else {
c = ch;
}
}
}
}
res
}
}
)+};
}
read_integer!(i8 i16 i32 i64 i128 isize u16 u32 u64 u128 usize);
macro_rules! tuple_readable {
($($name:ident)+) => {
impl<$($name: Readable), +> Readable for ($($name,)+) {
fn read(input: &mut Input) -> Self {
($($name::read(input),)+)
}
}
}
}
tuple_readable! {T}
tuple_readable! {T U}
tuple_readable! {T U V}
tuple_readable! {T U V X}
tuple_readable! {T U V X Y}
tuple_readable! {T U V X Y Z}
tuple_readable! {T U V X Y Z A}
tuple_readable! {T U V X Y Z A B}
tuple_readable! {T U V X Y Z A B C}
tuple_readable! {T U V X Y Z A B C D}
tuple_readable! {T U V X Y Z A B C D E}
tuple_readable! {T U V X Y Z A B C D E F}
impl Read for Input<'_> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if self.at == self.buf_read {
self.input.read(buf)
} else {
let mut i = 0;
while i < buf.len() && self.at < self.buf_read {
buf[i] = self.buf[self.at];
i += 1;
self.at += 1;
}
Ok(i)
}
}
}
}
pub mod output {
use crate::algo_lib::collections::vec_ext::default::default_vec;
use std::cmp::Reverse;
use std::io::stderr;
use std::io::Stderr;
use std::io::Write;
#[derive(Copy, Clone)]
pub enum BoolOutput {
YesNo,
YesNoCaps,
PossibleImpossible,
Custom(&'static str, &'static str),
}
impl BoolOutput {
pub fn output(&self, output: &mut Output, val: bool) {
(if val { self.yes() } else { self.no() }).write(output);
}
fn yes(&self) -> &str {
match self {
BoolOutput::YesNo => "Yes",
BoolOutput::YesNoCaps => "YES",
BoolOutput::PossibleImpossible => "Possible",
BoolOutput::Custom(yes, _) => yes,
}
}
fn no(&self) -> &str {
match self {
BoolOutput::YesNo => "No",
BoolOutput::YesNoCaps => "NO",
BoolOutput::PossibleImpossible => "Impossible",
BoolOutput::Custom(_, no) => no,
}
}
}
pub struct Output<'s> {
output: &'s mut dyn Write,
buf: Vec<u8>,
at: usize,
auto_flush: bool,
bool_output: BoolOutput,
precision: Option<usize>,
}
impl<'s> Output<'s> {
const DEFAULT_BUF_SIZE: usize = 4096;
pub fn new(output: &'s mut dyn Write) -> Self {
Self {
output,
buf: default_vec(Self::DEFAULT_BUF_SIZE),
at: 0,
auto_flush: false,
bool_output: BoolOutput::YesNoCaps,
precision: None,
}
}
pub fn new_with_auto_flush(output: &'s mut dyn Write) -> Self {
Self {
output,
buf: default_vec(Self::DEFAULT_BUF_SIZE),
at: 0,
auto_flush: true,
bool_output: BoolOutput::YesNoCaps,
precision: None,
}
}
pub fn flush(&mut self) {
if self.at != 0 {
self.output.write_all(&self.buf[..self.at]).unwrap();
self.output.flush().unwrap();
self.at = 0;
}
}
pub fn print<T: Writable>(&mut self, s: T) {
s.write(self);
self.maybe_flush();
}
pub fn print_line<T: Writable>(&mut self, s: T) {
self.print(s);
self.put(b'\n');
self.maybe_flush();
}
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]) {
self.print_per_line_iter(arg.iter());
}
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_line_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
self.print_iter(iter);
self.put(b'\n');
}
pub fn print_per_line_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
for e in iter {
e.write(self);
self.put(b'\n');
}
}
pub fn set_bool_output(&mut self, bool_output: BoolOutput) {
self.bool_output = bool_output;
}
pub fn set_precision(&mut self, precision: Option<usize>) {
self.precision = precision;
}
pub fn get_precision(&self) -> Option<usize> {
self.precision
}
}
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;
}
self.maybe_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 Writable for u8 {
fn write(&self, output: &mut Output) {
output.put(*self);
}
}
impl<T: Writable> Writable for [T] {
fn write(&self, output: &mut Output) {
output.print_iter(self.iter());
}
}
impl<T: Writable, const N: usize> Writable for [T; N] {
fn write(&self, output: &mut Output) {
output.print_iter(self.iter());
}
}
impl<T: Writable + ?Sized> Writable for &T {
fn write(&self, output: &mut Output) {
T::write(self, output)
}
}
impl<T: Writable> Writable for Vec<T> {
fn write(&self, output: &mut Output) {
self.as_slice().write(output);
}
}
impl Writable for () {
fn write(&self, _output: &mut 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!(u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
macro_rules! tuple_writable {
($name0:ident $($name:ident: $id:tt )*) => {
impl<$name0: Writable, $($name: Writable,)*> Writable for ($name0, $($name,)*) {
fn write(&self, out: &mut Output) {
self.0.write(out);
$(
out.put(b' ');
self.$id.write(out);
)*
}
}
}
}
tuple_writable! {T}
tuple_writable! {T U:1}
tuple_writable! {T U:1 V:2}
tuple_writable! {T U:1 V:2 X:3}
tuple_writable! {T U:1 V:2 X:3 Y:4}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6 B:7}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6 B:7 C:8}
impl<T: Writable> Writable for Option<T> {
fn write(&self, output: &mut Output) {
match self {
None => (-1).write(output),
Some(t) => t.write(output),
}
}
}
impl Writable for bool {
fn write(&self, output: &mut Output) {
let bool_output = output.bool_output;
bool_output.output(output, *self)
}
}
impl<T: Writable> Writable for Reverse<T> {
fn write(&self, output: &mut Output) {
self.0.write(output);
}
}
static mut ERR: Option<Stderr> = None;
pub fn err() -> Output<'static> {
unsafe {
if ERR.is_none() {
ERR = Some(stderr());
}
Output::new_with_auto_flush(ERR.as_mut().unwrap())
}
}
}
}
pub mod misc {
pub mod test_type {
pub enum TestType {
Single,
MultiNumber,
MultiEof,
}
pub enum TaskType {
Classic,
Interactive,
}
}
pub mod value {
use std::hash::Hash;
pub trait Value<T>: Copy + Eq + Hash {
fn val() -> T;
}
pub trait ConstValue<T>: Value<T> {
const VAL: T;
}
impl<T, V: ConstValue<T>> Value<T> for V {
fn val() -> T {
Self::VAL
}
}
#[macro_export]
macro_rules! value {
($name: ident: $t: ty = $val: expr) => {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Default)]
pub struct $name {}
impl $crate::algo_lib::misc::value::ConstValue<$t> for $name {
const VAL: $t = $val;
}
};
}
pub trait DynamicValue<T>: Value<T> {
//noinspection RsSelfConvention
fn set_val(t: T);
}
#[macro_export]
macro_rules! dynamic_value {
($name: ident: $t: ty, $val: ident) => {
static mut $val: Option<$t> = None;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Default)]
struct $name {}
impl $crate::algo_lib::misc::value::DynamicValue<$t> for $name {
fn set_val(t: $t) {
unsafe {
$val = Some(t);
}
}
}
impl $crate::algo_lib::misc::value::Value<$t> for $name {
fn val() -> $t {
unsafe { $val.unwrap() }
}
}
};
($name: ident: $t: ty) => {
dynamic_value!($name: $t, VAL);
};
($name: ident: $t: ty = $val: expr) => {
dynamic_value!($name: $t);
$name::set_val($val);
};
($name: ident: $t: ty = $val: expr, $val_static: ident) => {
dynamic_value!($name: $t, $val_static);
$name::set_val($val);
};
}
}
pub mod when {
#[macro_export]
macro_rules! when {
{$($cond: expr => $then: expr,)*} => {
match () {
$(_ if $cond => $then,)*
_ => unreachable!(),
}
};
{$($cond: expr => $then: expr,)* else $(=>)? $else: expr$(,)?} => {
match () {
$(_ if $cond => $then,)*
_ => $else,
}
};
}
}
}
pub mod numbers {
pub mod gcd {
use crate::algo_lib::numbers::num_traits::algebra::IntegerMultiplicationMonoid;
use crate::algo_lib::numbers::num_traits::algebra::IntegerSemiRingWithSub;
use crate::algo_lib::numbers::num_traits::algebra::One;
use crate::algo_lib::numbers::num_traits::algebra::SemiRingWithSub;
use crate::algo_lib::numbers::num_traits::algebra::Zero;
use crate::algo_lib::numbers::num_traits::wideable::Wideable;
use std::mem::swap;
pub fn extended_gcd<T: IntegerSemiRingWithSub + Wideable + Copy>(a: T, b: T) -> (T, T::W, T::W)
where
T::W: Copy + SemiRingWithSub,
{
if a == T::zero() {
(b, T::W::zero(), T::W::one())
} else {
let (d, y, mut x) = extended_gcd(b % a, a);
x -= T::W::from(b / a) * y;
(d, x, y)
}
}
pub fn gcd<T: Copy + Zero + IntegerMultiplicationMonoid>(mut a: T, mut b: T) -> T {
while b != T::zero() {
a %= b;
swap(&mut a, &mut b);
}
a
}
pub fn lcm<T: Copy + Zero + IntegerMultiplicationMonoid>(a: T, b: T) -> T {
(a / gcd(a, b)) * b
}
}
pub mod mod_int {
use crate::algo_lib::collections::fx_hash_map::FxHashMap;
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::value::Value;
use crate::algo_lib::numbers::gcd::extended_gcd;
use crate::algo_lib::numbers::num_traits::algebra::Field;
use crate::algo_lib::numbers::num_traits::algebra::IntegerRing;
use crate::algo_lib::numbers::num_traits::algebra::One;
use crate::algo_lib::numbers::num_traits::algebra::Ring;
use crate::algo_lib::numbers::num_traits::algebra::Zero;
use crate::algo_lib::numbers::num_traits::as_index::AsIndex;
use crate::algo_lib::numbers::num_traits::invertible::Invertible;
use crate::algo_lib::numbers::num_traits::wideable::Wideable;
use crate::value;
use crate::when;
use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hash;
use std::marker::PhantomData;
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::Neg;
use std::ops::Sub;
use std::ops::SubAssign;
pub trait BaseModInt: Field + Copy {
type W: IntegerRing + Copy + From<Self::T>;
type T: IntegerRing + Ord + Copy + Wideable<W = Self::W>;
fn from(v: Self::T) -> Self;
fn module() -> Self::T;
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Default)]
pub struct ModInt<T, V: Value<T>> {
n: T,
phantom: PhantomData<V>,
}
impl<T: Copy, V: Value<T>> ModInt<T, V> {
pub fn val(&self) -> T {
self.n
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> ModInt<T, V> {
unsafe fn unchecked_new(n: T) -> Self {
debug_assert!(n >= T::zero() && n < V::val());
Self {
n,
phantom: Default::default(),
}
}
unsafe fn maybe_subtract_mod(mut n: T) -> T {
debug_assert!(n < V::val() + V::val() && n >= T::zero());
if n >= V::val() {
n -= V::val();
}
n
}
}
impl<T: IntegerRing + Ord + Copy, V: Value<T>> ModInt<T, V> {
pub fn new(n: T) -> Self {
unsafe { Self::unchecked_new(Self::maybe_subtract_mod(n % (V::val()) + V::val())) }
}
}
impl<T: Copy + IntegerRing + Ord + Wideable + Hash, V: Value<T>> ModInt<T, V>
where
T::W: Copy + IntegerRing,
{
pub fn log(&self, alpha: Self) -> T {
let mut base = FxHashMap::default();
let mut exp = T::zero();
let mut pow = Self::one();
let mut inv = *self;
let alpha_inv = alpha.inv().unwrap();
while exp * exp < Self::module() {
if inv == Self::one() {
return exp;
}
base.insert(inv, exp);
exp += T::one();
pow *= alpha;
inv *= alpha_inv;
}
let step = pow;
let mut i = T::one();
loop {
if let Some(b) = base.get(&pow) {
break exp * i + *b;
}
pow *= step;
i += T::one();
}
}
}
impl<T: Wideable + Ring + Ord + Copy, V: Value<T>> ModInt<T, V>
where
T::W: IntegerRing,
{
pub fn new_from_wide(n: T::W) -> Self {
unsafe {
Self::unchecked_new(Self::maybe_subtract_mod(
T::downcast(n % V::val().into()) + V::val(),
))
}
}
}
impl<T: Copy + IntegerRing + Ord + Wideable, V: Value<T>> Invertible for ModInt<T, V>
where
T::W: Copy + IntegerRing,
{
type Output = Self;
fn inv(&self) -> Option<Self> {
let (g, x, _) = extended_gcd(self.n, V::val());
if g != T::one() {
None
} else {
Some(Self::new_from_wide(x))
}
}
}
impl<T: IntegerRing + Ord + Copy + Wideable, V: Value<T>> BaseModInt for ModInt<T, V>
where
T::W: IntegerRing + Copy,
{
type W = T::W;
type T = T;
fn from(v: Self::T) -> Self {
Self::new(v)
}
fn module() -> T {
V::val()
}
}
impl<T: IntegerRing + Ord + Copy, V: Value<T>> From<T> for ModInt<T, V> {
fn from(n: T) -> Self {
Self::new(n)
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> AddAssign for ModInt<T, V> {
fn add_assign(&mut self, rhs: Self) {
self.n = unsafe { Self::maybe_subtract_mod(self.n + rhs.n) };
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> Add for ModInt<T, V> {
type Output = Self;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> SubAssign for ModInt<T, V> {
fn sub_assign(&mut self, rhs: Self) {
self.n = unsafe { Self::maybe_subtract_mod(self.n + V::val() - rhs.n) };
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> Sub for ModInt<T, V> {
type Output = Self;
fn sub(mut self, rhs: Self) -> Self::Output {
self -= rhs;
self
}
}
impl<T: IntegerRing + Ord + Copy + Wideable, V: Value<T>> MulAssign for ModInt<T, V>
where
T::W: IntegerRing + Copy,
{
fn mul_assign(&mut self, rhs: Self) {
self.n = T::downcast(T::W::from(self.n) * T::W::from(rhs.n) % T::W::from(V::val()));
}
}
impl<T: IntegerRing + Ord + Copy + Wideable, V: Value<T>> Mul for ModInt<T, V>
where
T::W: IntegerRing + Copy,
{
type Output = Self;
fn mul(mut self, rhs: Self) -> Self::Output {
self *= rhs;
self
}
}
impl<T: IntegerRing + Ord + Copy + Wideable, V: Value<T>> DivAssign for ModInt<T, V>
where
T::W: IntegerRing + Copy,
{
#[allow(clippy::suspicious_op_assign_impl)]
fn div_assign(&mut self, rhs: Self) {
*self *= rhs.inv().unwrap();
}
}
impl<T: IntegerRing + Ord + Copy + Wideable, V: Value<T>> Div for ModInt<T, V>
where
T::W: IntegerRing + Copy,
{
type Output = Self;
fn div(mut self, rhs: Self) -> Self::Output {
self /= rhs;
self
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> Neg for ModInt<T, V> {
type Output = Self;
fn neg(mut self) -> Self::Output {
self.n = unsafe { Self::maybe_subtract_mod(V::val() - self.n) };
self
}
}
impl<T: Display, V: Value<T>> Display for ModInt<T, V> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
<T as Display>::fmt(&self.n, f)
}
}
impl<T: IntegerRing + Ord + Copy + Readable, V: Value<T>> Readable for ModInt<T, V> {
fn read(input: &mut Input) -> Self {
Self::new(T::read(input))
}
}
impl<T: Writable, V: Value<T>> Writable for ModInt<T, V> {
fn write(&self, output: &mut Output) {
self.n.write(output);
}
}
impl<T: Ring + Ord + Copy, V: Value<T>> Zero for ModInt<T, V> {
fn zero() -> Self {
unsafe { Self::unchecked_new(T::zero()) }
}
}
impl<T: IntegerRing + Ord + Copy, V: Value<T>> One for ModInt<T, V> {
fn one() -> Self {
Self::new(T::one())
}
}
impl<T, V: Value<T>> Wideable for ModInt<T, V> {
type W = Self;
fn downcast(w: Self::W) -> Self {
w
}
}
impl<T: IntegerRing + Ord + Copy + Wideable + Display + AsIndex, V: Value<T>> std::fmt::Debug
for ModInt<T, V>
where
T::W: IntegerRing + Copy,
{
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
let max = T::from_index(100);
when! {
self.n <= max => write!(f, "{}", self.n),
self.n >= V::val() - max => write!(f, "{}", self.n - V::val()),
else => {
let mut denominator = T::one();
while denominator < max {
let mut num = T::one();
while num < max {
if Self::new(num) / Self::new(denominator) == *self {
return write!(f, "{}/{}", num, denominator);
}
if -Self::new(num) / Self::new(denominator) == *self {
return write!(f, "-{}/{}", num, denominator);
}
num += T::one();
}
denominator += T::one();
}
write!(f, "(?? {} ??)", self.n)
},
}
}
}
impl<T: IntegerRing + Ord + Copy + AsIndex, V: Value<T>> AsIndex for ModInt<T, V> {
fn from_index(idx: usize) -> Self {
Self::new(T::from_index(idx))
}
fn to_index(self) -> usize {
self.n.to_index()
}
}
value!(Val7: i32 = 1_000_000_007);
pub type ModInt7 = ModInt<i32, Val7>;
value!(Val9: i32 = 1_000_000_009);
pub type ModInt9 = ModInt<i32, Val9>;
value!(ValF: i32 = 998_244_353);
pub type ModIntF = ModInt<i32, ValF>;
}
pub mod mod_utils {
use crate::algo_lib::numbers::mod_int::BaseModInt;
use crate::algo_lib::numbers::num_traits::as_index::AsIndex;
use crate::algo_lib::numbers::num_utils::factorial;
use crate::algo_lib::numbers::num_utils::factorials;
pub fn inverses<M: BaseModInt>(len: usize) -> Vec<M>
where
M::T: AsIndex,
{
let mut res = Vec::new();
if len > 0 {
res.push(M::zero());
}
if len > 1 {
res.push(M::one());
}
while res.len() < len {
res.push(
res[M::module().to_index() % res.len()]
* (M::from(M::module() / (M::T::from_index(res.len()))).neg()),
);
}
res
}
pub fn inverse_factorials<M: BaseModInt>(len: usize) -> Vec<M>
where
M::T: AsIndex,
{
let mut res = inverses(len);
if len > 0 {
res[0] = M::one();
}
for i in 1..len {
let last = res[i - 1];
res[i] *= last;
}
res
}
pub struct Combinations<M: BaseModInt>
where
M::T: AsIndex,
{
fact: Vec<M>,
inv_fact: Vec<M>,
}
impl<M: BaseModInt + AsIndex> Combinations<M>
where
M::T: AsIndex,
{
pub fn new(len: usize) -> Self {
Self {
fact: factorials(len),
inv_fact: inverse_factorials(len),
}
}
pub fn c(&self, n: usize, k: usize) -> M {
if n < k {
M::zero()
} else {
self.fact[n] * self.inv_fact[k] * self.inv_fact[n - k]
}
}
pub fn comb_with_rep(&self, n: usize, k: usize) -> M {
self.c(n + k - 1, k)
}
pub fn c_inv(&self, n: usize, k: usize) -> M {
self.inv_fact[n] * self.fact[k] * self.fact[n - k]
}
pub fn fact(&self, n: usize) -> M {
self.fact[n]
}
pub fn inv_fact(&self, n: usize) -> M {
self.inv_fact[n]
}
}
pub fn combinations<M: BaseModInt + AsIndex>(n: usize, mut k: usize) -> M {
if k > n {
return M::zero();
}
if k > n - k {
k = n - k;
}
let mut res = M::one();
for i in n - k + 1..=n {
res *= M::from_index(i);
}
res /= factorial(k);
res
}
}
pub mod num_traits {
pub mod algebra {
use crate::algo_lib::numbers::num_traits::invertible::Invertible;
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::Neg;
use std::ops::Rem;
use std::ops::RemAssign;
use std::ops::Sub;
use std::ops::SubAssign;
pub trait Zero {
fn zero() -> Self;
}
pub trait One {
fn one() -> Self;
}
pub trait AdditionMonoid: Add<Output = Self> + AddAssign + Zero + Eq + Sized {}
impl<T: Add<Output = Self> + AddAssign + Zero + Eq> AdditionMonoid for T {}
pub trait AdditionMonoidWithSub: AdditionMonoid + Sub<Output = Self> + SubAssign {}
impl<T: AdditionMonoid + Sub<Output = Self> + SubAssign> AdditionMonoidWithSub for T {}
pub trait AdditionGroup: AdditionMonoidWithSub + Neg<Output = Self> {}
impl<T: AdditionMonoidWithSub + Neg<Output = Self>> AdditionGroup for T {}
pub trait MultiplicationMonoid: Mul<Output = Self> + MulAssign + One + Eq + Sized {}
impl<T: Mul<Output = Self> + MulAssign + One + Eq> MultiplicationMonoid for T {}
pub trait IntegerMultiplicationMonoid:
MultiplicationMonoid + Div<Output = Self> + Rem<Output = Self> + DivAssign + RemAssign
{
}
impl<T: MultiplicationMonoid + Div<Output = Self> + Rem<Output = Self> + DivAssign + RemAssign>
IntegerMultiplicationMonoid for T
{
}
pub trait MultiplicationGroup:
MultiplicationMonoid + Div<Output = Self> + DivAssign + Invertible<Output = Self>
{
}
impl<T: MultiplicationMonoid + Div<Output = Self> + DivAssign + Invertible<Output = Self>>
MultiplicationGroup for T
{
}
pub trait SemiRing: AdditionMonoid + MultiplicationMonoid {}
impl<T: AdditionMonoid + MultiplicationMonoid> SemiRing for T {}
pub trait SemiRingWithSub: AdditionMonoidWithSub + SemiRing {}
impl<T: AdditionMonoidWithSub + SemiRing> SemiRingWithSub for T {}
pub trait Ring: SemiRing + AdditionGroup {}
impl<T: SemiRing + AdditionGroup> Ring for T {}
pub trait IntegerSemiRing: SemiRing + IntegerMultiplicationMonoid {}
impl<T: SemiRing + IntegerMultiplicationMonoid> IntegerSemiRing for T {}
pub trait IntegerSemiRingWithSub: SemiRingWithSub + IntegerSemiRing {}
impl<T: SemiRingWithSub + IntegerSemiRing> IntegerSemiRingWithSub for T {}
pub trait IntegerRing: IntegerSemiRing + Ring {}
impl<T: IntegerSemiRing + Ring> IntegerRing for T {}
pub trait Field: Ring + MultiplicationGroup {}
impl<T: Ring + MultiplicationGroup> Field for T {}
macro_rules! zero_one_integer_impl {
($($t: ident)+) => {$(
impl Zero for $t {
fn zero() -> Self {
0
}
}
impl One for $t {
fn one() -> Self {
1
}
}
)+};
}
zero_one_integer_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize);
}
pub mod as_index {
pub trait AsIndex {
fn from_index(idx: usize) -> Self;
fn to_index(self) -> usize;
}
macro_rules! from_index_impl {
($($t: ident)+) => {$(
impl AsIndex for $t {
fn from_index(idx: usize) -> Self {
idx as $t
}
fn to_index(self) -> usize {
self as usize
}
}
)+};
}
from_index_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize);
}
pub mod invertible {
pub trait Invertible {
type Output;
fn inv(&self) -> Option<Self::Output>;
}
}
pub mod wideable {
use std::convert::From;
pub trait Wideable: Sized {
type W: From<Self>;
fn downcast(w: Self::W) -> Self;
}
macro_rules! wideable_impl {
($($t: ident $w: ident),+) => {$(
impl Wideable for $t {
type W = $w;
fn downcast(w: Self::W) -> Self {
w as $t
}
}
)+};
}
wideable_impl!(i64 i128, i32 i64, i16 i32, i8 i16, u64 u128, u32 u64, u16 u32, u8 u16);
}
}
pub mod num_utils {
use crate::algo_lib::numbers::num_traits::algebra::AdditionMonoid;
use crate::algo_lib::numbers::num_traits::algebra::IntegerRing;
use crate::algo_lib::numbers::num_traits::algebra::MultiplicationMonoid;
use crate::algo_lib::numbers::num_traits::as_index::AsIndex;
pub fn factorials<T: MultiplicationMonoid + Copy + AsIndex>(len: usize) -> Vec<T> {
let mut res = Vec::new();
if len > 0 {
res.push(T::one());
}
while res.len() < len {
res.push((*res.last().unwrap()) * T::from_index(res.len()));
}
res
}
pub fn powers<T: MultiplicationMonoid + Copy>(base: T, len: usize) -> Vec<T> {
let mut res = Vec::new();
if len > 0 {
res.push(T::one());
}
while res.len() < len {
res.push((*res.last().unwrap()) * base);
}
res
}
pub struct Powers<T: MultiplicationMonoid + Copy> {
small: Vec<T>,
big: Vec<T>,
}
impl<T: MultiplicationMonoid + Copy> Powers<T> {
pub fn new(base: T, len: usize) -> Self {
let small = powers(base, len);
let big = powers(small[len - 1] * base, len);
Self { small, big }
}
pub fn power(&self, exp: usize) -> T {
debug_assert!(exp < self.small.len() * self.small.len());
self.big[exp / self.small.len()] * self.small[exp % self.small.len()]
}
}
pub fn factorial<T: MultiplicationMonoid + AsIndex>(n: usize) -> T {
let mut res = T::one();
for i in 1..=n {
res *= T::from_index(i);
}
res
}
pub trait PartialSums<T> {
fn partial_sums(&self) -> Vec<T>;
}
impl<T: AdditionMonoid + Copy> PartialSums<T> for [T] {
fn partial_sums(&self) -> Vec<T> {
let mut res = Vec::with_capacity(self.len() + 1);
res.push(T::zero());
for i in self.iter() {
res.push(*res.last().unwrap() + *i);
}
res
}
}
pub trait UpperDiv {
fn upper_div(self, other: Self) -> Self;
}
impl<T: IntegerRing + Copy> UpperDiv for T {
fn upper_div(self, other: Self) -> Self {
(self + other - Self::one()) / other
}
}
}
pub mod number_ext {
use crate::algo_lib::numbers::num_traits::algebra::IntegerSemiRing;
use crate::algo_lib::numbers::num_traits::algebra::MultiplicationMonoid;
use crate::algo_lib::numbers::num_traits::as_index::AsIndex;
use std::ops::Mul;
pub trait Power {
#[must_use]
fn power<T: IntegerSemiRing + Copy>(&self, exp: T) -> Self;
}
impl<S: MultiplicationMonoid + Copy> Power for S {
fn power<T: IntegerSemiRing + Copy>(&self, exp: T) -> Self {
if exp == T::zero() {
S::one()
} else {
let mut res = self.power(exp / (T::one() + T::one()));
res *= res;
if exp % (T::one() + T::one()) == T::one() {
res *= *self;
}
res
}
}
}
pub trait NumDigs {
fn num_digs(&self) -> usize;
}
impl<S: IntegerSemiRing + AsIndex + Copy> NumDigs for S {
fn num_digs(&self) -> usize {
let mut copy = *self;
let ten = S::from_index(10);
let mut res = 0;
while copy != S::zero() {
copy /= ten;
res += 1;
}
res
}
}
pub trait SumDigs {
fn sum_digs(&self) -> Self;
}
impl<S: IntegerSemiRing + AsIndex + Copy> SumDigs for S {
fn sum_digs(&self) -> S {
let mut copy = *self;
let ten = S::from_index(10);
let mut res = S::zero();
while copy != S::zero() {
res += copy % ten;
copy /= ten;
}
res
}
}
pub trait Square {
fn square(self) -> Self;
}
impl<T: Mul<Output = T> + Copy> Square for T {
fn square(self) -> Self {
self * self
}
}
}
pub mod prime_fft {
use crate::algo_lib::collections::slice_ext::legacy_fill::LegacyFill;
use crate::algo_lib::numbers::mod_int::BaseModInt;
use crate::algo_lib::numbers::num_traits::algebra::IntegerRing;
use crate::algo_lib::numbers::num_traits::algebra::One;
use crate::algo_lib::numbers::num_traits::algebra::Zero;
use crate::algo_lib::numbers::number_ext::Power;
pub struct PrimeFFT<M: BaseModInt> {
root: M,
reverse_root: M,
root_power: M::T,
aa: Vec<M>,
bb: Vec<M>,
}
impl<M: BaseModInt> Default for PrimeFFT<M> {
fn default() -> Self {
Self::new()
}
}
impl<M: BaseModInt> PrimeFFT<M> {
pub fn new() -> Self {
let mut exp = M::T::zero();
let mut root_power = M::T::one();
while (M::module() - M::T::one()) % (root_power + root_power) == M::T::zero() {
exp = root_power;
root_power += root_power;
}
let mut i = M::one() + M::one();
loop {
if i.power(exp) != M::one() && i.power(root_power) == M::one() {
break Self {
root: i,
reverse_root: i.inv().unwrap(),
root_power,
aa: Vec::new(),
bb: Vec::new(),
};
}
i += M::one();
}
}
pub fn multiply_res(&mut self, a: &[M], b: &[M], res: &mut Vec<M>) {
if a.is_empty() || b.is_empty() {
res.legacy_fill(M::zero());
return;
}
let res_len = a.len() + b.len() - 1;
if res.len() < res_len {
res.reserve(res_len - res.len());
for _ in res.len()..res_len {
res.push(M::zero());
}
}
self.multiply_fix_len(a, b, res);
}
pub fn multiply_fix_len(&mut self, a: &[M], b: &[M], res: &mut [M]) {
let res_len = res.len();
if res_len <= Self::BORDER_LEN {
res.legacy_fill(M::zero());
for (i, f) in a.iter().enumerate() {
for (j, s) in b.iter().enumerate() {
if i + j < res.len() {
res[i + j] += (*f) * (*s);
} else {
break;
}
}
}
return;
}
let mut size = 1;
let mut size_t = M::T::one();
while size < res_len {
size *= 2;
size_t += size_t;
}
if self.root_power < size_t {
panic!("unsuitable modulo");
}
if self.aa.len() < size {
let was_len = self.aa.len();
self.aa[..was_len.min(a.len())].copy_from_slice(&a[..was_len.min(a.len())]);
self.aa[was_len.min(a.len())..].legacy_fill(M::zero());
self.aa.extend_from_slice(&a[was_len.min(a.len())..]);
self.aa.reserve(size - self.aa.len());
for _ in self.aa.len()..size {
self.aa.push(M::zero());
}
} else {
self.aa[..a.len()].copy_from_slice(a);
self.aa[a.len()..size].legacy_fill(M::zero());
}
Self::fft(
&mut self.aa[..size],
false,
self.root,
self.root_power,
size_t,
);
if a == b {
for i in self.aa[..size].iter_mut() {
*i *= *i;
}
} else {
if self.bb.len() < size {
let was_len = self.bb.len();
self.bb[..was_len.min(b.len())].copy_from_slice(&b[..was_len.min(b.len())]);
self.bb[was_len.min(b.len())..].legacy_fill(M::zero());
self.bb.extend_from_slice(&b[was_len.min(b.len())..]);
self.bb.reserve(size - self.bb.len());
for _ in self.bb.len()..size {
self.bb.push(M::zero());
}
} else {
self.bb[..b.len()].copy_from_slice(b);
self.bb[b.len()..size].legacy_fill(M::zero());
}
Self::fft(
&mut self.bb[..size],
false,
self.root,
self.root_power,
size_t,
);
for (i, j) in self.aa[..size].iter_mut().zip(self.bb[..size].iter()) {
*i *= *j;
}
}
Self::fft(
&mut self.aa[..size],
true,
self.reverse_root,
self.root_power,
size_t,
);
res.copy_from_slice(&self.aa[..res_len]);
}
pub fn multiply(&mut self, a: &[M], b: &[M]) -> Vec<M> {
if a.is_empty() || b.is_empty() {
Vec::new()
} else {
let mut res = vec![M::zero(); a.len() + b.len() - 1];
self.multiply_res(a, b, &mut res);
res
}
}
pub fn power<T: IntegerRing + Copy>(&mut self, a: &[M], exp: T) -> Vec<M> {
let mut res = Vec::new();
let mut temp = Vec::new();
self.power_impl(a, exp, &mut res, &mut temp);
res
}
fn power_impl<T: IntegerRing + Copy>(
&mut self,
a: &[M],
exp: T,
res: &mut Vec<M>,
temp: &mut Vec<M>,
) {
if exp == T::zero() {
res.push(M::one());
return;
}
let two = T::one() + T::one();
if exp % two == T::zero() {
self.power_impl(a, exp / two, temp, res);
self.multiply_res(temp, temp, res);
} else {
self.power_impl(a, exp - T::one(), temp, res);
self.multiply_res(temp, a, res);
}
}
const BORDER_LEN: usize = 100;
fn fft(a: &mut [M], invert: bool, root: M, root_power: M::T, size_t: M::T)
where
M::T: Copy,
{
let mut j = 0usize;
for i in 1..a.len() {
let mut bit = a.len() >> 1;
while j >= bit {
j -= bit;
bit >>= 1;
}
j += bit;
if i < j {
a.swap(i, j);
}
}
let mut len = 2;
let mut len_t = M::T::one() + M::T::one();
while len <= a.len() {
let mut w_len = root;
let mut i = len_t;
while i < root_power {
w_len *= w_len;
i += i;
}
let half = len >> 1;
for i in (0..a.len()).step_by(len) {
let mut w = M::one();
for j in 0..half {
let u = a[i + j];
let v = a[i + j + half] * w;
a[i + j] = u + v;
a[i + j + half] = u - v;
w *= w_len;
}
}
len <<= 1;
len_t += len_t;
}
if invert {
let inv_size = M::from(size_t).inv().unwrap();
for i in a {
*i *= inv_size;
}
}
}
}
}
}
}
fn main() {
let mut sin = std::io::stdin();
let input = algo_lib::io::input::Input::new(&mut sin);
let mut stdout = std::io::stdout();
let output = algo_lib::io::output::Output::new(&mut stdout);
solution::run(input, output);
}
这程序好像有点Bug,我给组数据试试?
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 2132kb
input:
4 2 2 1 3 2 4 3 1 10 10 10 1 3 20 10 30 3 4 1 1 4 5 1 4 1 9 1 9 8 10
output:
56 60 60 855346687
result:
ok 4 number(s): "56 60 60 855346687"
Test #2:
score: 0
Accepted
time: 0ms
memory: 2184kb
input:
1 2 2 0 0 998244352 998244352
output:
998244345
result:
ok 1 number(s): "998244345"
Test #3:
score: 0
Accepted
time: 73ms
memory: 2396kb
input:
900 1 1 810487041 1 2 569006976 247513378 1 3 424212910 256484544 661426830 1 4 701056586 563296095 702740883 723333858 1 5 725786515 738465053 821758167 170452477 34260723 1 6 204184507 619884535 208921865 898995024 768400582 369477346 1 7 225635227 321139203 724076812 439129905 405005469 369864252...
output:
810487041 495026756 540662911 541929691 118309348 270925149 575366228 709974238 761347712 304011276 14811741 366145628 638305530 240546928 484276475 603344008 926633861 161768904 239961447 329781933 315752584 578075668 259941994 600147169 402221164 890998500 154285994 181862417 47930994 273729619 64...
result:
ok 900 numbers
Test #4:
score: 0
Accepted
time: 97ms
memory: 2224kb
input:
400 1 995 548100968 635656907 177366910 971271357 314579375 529572241 948721678 455918644 95745688 164857981 499083775 827896554 496889261 111294651 646048809 758286431 163045934 917399362 189372614 267754648 966443706 921589740 228089960 473153545 482816423 37567957 495730380 864445591 568695110 78...
output:
954668084 677509135 636173666 415373646 477286237 209886549 398423120 24466622 672440292 390142124 498517438 305197486 239833057 500821845 475519894 347179487 974036742 810602822 75196204 48378743 393961176 290898056 957916898 434124418 663457674 225283495 704304053 338701802 670053839 137083082 165...
result:
ok 400 numbers
Test #5:
score: 0
Accepted
time: 161ms
memory: 2784kb
input:
40 92 99 14480275 12892621 932457558 584861415 926346518 101583802 498448003 884757899 463949215 661256632 872663851 651132350 565253214 18404795 810166895 145370572 123351313 298382303 777283720 775900024 613503856 817112784 713304484 541301622 595768594 550989875 960159831 571815058 777864097 3608...
output:
614712898 16225927 313765200 824491114 60971514 769510634 58341639 808667102 527187053 319496150 267177120 409701892 245708713 115397703 928197397 533118123 931076329 448328887 672878477 180728812 385639338 504093069 846218180 981546177 906805965 315620628 863877552 348963788 781585156 982673320 275...
result:
ok 40 numbers
Test #6:
score: 0
Accepted
time: 142ms
memory: 2608kb
input:
40 86 92 479103936 690362573 387313968 428679987 770097821 67859949 744428797 919332570 530162857 389639443 851979342 310332074 863845681 155743453 442066584 996725021 385646576 447381083 64960590 818019444 260564007 16381359 36238584 609449698 12466296 532193395 262308857 279184524 454814687 400578...
output:
147127348 995441625 947321329 200561175 846810174 626764591 235790337 30932003 384829067 254218916 20342301 451884441 634808121 241161955 246093492 515701050 978130791 502129313 3431507 775910032 464454612 153447682 53092548 316439192 101505498 40191013 225025922 133184210 209384134 330521977 360716...
result:
ok 40 numbers
Test #7:
score: 0
Accepted
time: 189ms
memory: 11708kb
input:
2 447 447 790583748 764745604 779691526 67598288 308196334 738524513 685610494 336125979 294155123 651917356 898366384 420012139 529304950 133567869 630219750 62853597 606184670 383809162 43962071 826608376 652871696 860138865 675639996 444122802 823442992 841633845 125418467 211407031 726738308 984...
output:
506347658 891054810
result:
ok 2 number(s): "506347658 891054810"
Test #8:
score: 0
Accepted
time: 197ms
memory: 11752kb
input:
2 100 2000 414412015 610256524 548060717 581032168 761297097 50124687 831351681 906381893 842125801 82512258 734351512 844649420 370666628 791011946 232557748 968208094 238084359 933173727 306257334 509581201 774756848 370039888 322700146 641635730 8423279 909781921 238370638 28574480 725141803 9941...
output:
380238486 147107381
result:
ok 2 number(s): "380238486 147107381"
Test #9:
score: 0
Accepted
time: 201ms
memory: 11760kb
input:
2 2000 100 432504867 225538929 546658423 260257767 682179463 892187612 142884587 872658039 89862243 117086929 104310686 342803717 47992235 148221787 695186286 875318238 264248632 320257869 568552597 54600213 364423602 412159309 666014765 235168890 795627687 977929998 351322809 9778000 723545298 1693...
output:
807761546 460321345
result:
ok 2 number(s): "807761546 460321345"
Test #10:
score: 0
Accepted
time: 194ms
memory: 11752kb
input:
2 10 20000 450597719 675029617 315027614 635737834 439025757 505777670 590615658 142679716 637832921 847916068 472514213 71186529 723562195 273447466 297524284 782428382 428366719 869622434 528857976 735817391 650344824 152288845 779100871 130691934 584587742 513859676 996493379 687235989 189730396 ...
output:
579362183 459093435
result:
ok 2 number(s): "579362183 459093435"
Test #11:
score: 0
Accepted
time: 197ms
memory: 11760kb
input:
2 20000 10 770680455 822530420 615615204 314963433 892126521 815622197 900392916 410945746 187559247 278510970 538727855 101559225 98897919 326911775 760152822 689538526 60266407 256706575 791153240 418790216 772229976 194408266 426161021 328204862 71557913 976272337 111201197 504403438 188133891 58...
output:
30164141 385139412
result:
ok 2 number(s): "30164141 385139412"
Test #12:
score: 0
Accepted
time: 189ms
memory: 12540kb
input:
2 100000 2 224212357 458006968 163025536 269449920 699657932 932776912 420937536 166351734 685658904 344666962 946460500 884461444 228370491 174980092 646368291 854381092 617669653 366836379 717071379 463349902 749408189 163205331 665200568 666647060 230069001 195048922 357469436 37819596 212080713 ...
output:
188269415 372357321
result:
ok 2 number(s): "188269415 372357321"
Test #13:
score: 0
Accepted
time: 200ms
memory: 11696kb
input:
2 2 100000 242305209 73289374 463613125 946919872 154514343 546366969 34460325 132627880 629649815 379241632 14429790 612844256 207685982 530434285 412742360 761491236 249569341 450174989 677376758 146322726 339074943 507314636 10270834 864159988 715283525 729222953 772411491 19023116 374520280 8624...
output:
178386797 319825470
result:
ok 2 number(s): "178386797 319825470"
Test #14:
score: 0
Accepted
time: 205ms
memory: 11676kb
input:
2 1 200000 562387945 522780061 928236786 626145471 377386592 856211496 180201513 702883794 179376140 808080887 382633317 110998553 883255942 655659964 711334827 668601380 413687428 303285085 939672021 525550020 460960094 549434056 957565221 759683032 202253696 797371030 885363662 532445034 674913659...
output:
499141558 710898596
result:
ok 2 number(s): "499141558 710898596"
Extra Test:
score: 0
Extra Test Passed