結果

問題 No.1917 LCMST
ユーザー rhoo
提出日時 2025-07-16 10:24:54
言語 Rust
(1.83.0 + proconio)
結果
MLE  
実行時間 -
コード長 10,260 bytes
コンパイル時間 12,552 ms
コンパイル使用メモリ 398,560 KB
実行使用メモリ 812,928 KB
最終ジャッジ日時 2025-07-16 10:27:05
合計ジャッジ時間 112,601 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 32 TLE * 1 MLE * 8 -- * 1
権限があれば一括ダウンロードができます

ソースコード

diff #

#![allow(unused_imports,non_snake_case,dead_code)]
use std::{cmp::Reverse as Rev,ops::Range,collections::*,iter::*};
use proconio::{marker::*,*};



// LCMST

type HashMap<K,V>=rustc_hash::FxHashMap<K,V>;



#[fastout]
fn main(){
    input!{
        n:usize,
        a:[usize;n],
    }

    let mut era=vec![!0;1e6 as usize+5];
    for i in 2..era.len(){
        if era[i]!=!0{
            continue;
        }
        for j in 1..{
            if era.len()<=i*j{
                break;
            }
            era[i*j]=i;
        }
    }

    let divisor=|mut n:usize|->Vec<usize>{
        let mut ps=vec![];
        while era[n]!=!0{
            let p=era[n];
            let mut cnt=0;
            while n%p==0{
                cnt+=1;
                n/=p;
            }
            ps.push((p,cnt));
        }

        if n!=1{
            ps.push((n,1));
        }

        fn rec(ps:&[(usize,usize)],i:usize,mut div:usize,divs:&mut Vec<usize>){
            if i==!0{
                divs.push(div);
                return;
            }
            let (p,cnt)=ps[i];
            for _ in 0..=cnt{
                rec(ps,i-1,div,divs);
                div*=p;
            }
        }

        let mut divs=vec![];
        rec(&ps,ps.len()-1,1,&mut divs);
        divs
    };

    let divs=(0..n).map(|i|divisor(a[i])).collect::<Vec<_>>();
    let mut id_to_div=divs.iter().flatten().copied().collect::<Vec<_>>();
    id_to_div.sort_unstable();
    id_to_div.dedup();
    let mut div_to_id=HashMap::default();

    for i in 0..id_to_div.len(){
        div_to_id.insert(id_to_div[i],i);
    }

    let mut div_set=vec![vec![];id_to_div.len()];
    for i in 0..n{
        for &d in &divs[i]{
            let id=div_to_id[&d];
            div_set[id].push(a[i]);
        }
    }
    for i in 0..div_set.len(){
        div_set[i].sort_unstable_by_key(|&t|!t);
    }

    // type MultiSet=BTreeMap<usize,usize>;
    // fn add(set:&mut MultiSet,a:usize){
    //     *set.entry(a).or_insert(0)+=1;
    // }
    // fn rem(set:&mut MultiSet,a:usize){
    //     let e=set.get_mut(&a).unwrap();
    //     *e-=1;
    //     if *e==0{
    //         set.remove(&a);
    //     }
    // }

    #[derive(Clone,Debug)]
    struct Queue{
        d:usize,
        que:usize,
        co_que:Vec<usize>,
        w:usize,
    }

    let init_que=|d:usize|{
        let id=div_to_id[&d];
        Queue{
            d,
            que:!0,
            co_que:div_set[id].clone(),
            w:!0,
        }
    };

    let mut cnt=vec![0;1e6 as usize+5];
    for i in 0..n{
        cnt[a[i]]+=1;
    }

    let mut que=id_to_div.iter().map(|&d|init_que(d)).collect::<Vec<Queue>>();
    let mut min=BTreeSet::new();
    
    cap!{
        #![&a:[usize],&mut que:[Queue],&divs:[Vec<usize>],&div_to_id:rustc_hash::FxHashMap<usize,usize>,
            &mut min:BTreeSet<(usize,usize)>,&mut cnt:[usize]]
        
        // a[i]をprimとして確定させる
        fn mov(i:usize){
            cnt[a[i]]-=1;

            for &n in &divs[i]{
                let id=div_to_id[&n];
                let que=&mut que[id];
                if que.w!=!0{
                    min.remove(&(que.w,que.d));
                }
                
                que.que=que.que.min(a[i]);
                while let Some(&v)=que.co_que.last(){
                    if cnt[v]==0{
                        que.co_que.pop().unwrap();
                    } else{
                        break;
                    }
                }
                
                if que.que!=!0 && !que.co_que.is_empty(){
                    let m0=que.que;
                    let m1=que.co_que.last().unwrap();
                    que.w=m0/que.d*m1;
                    min.insert((que.w,que.d));
                } else{
                    que.w=!0;
                }
            }
        }
    }
    
    let mut index=HashMap::default();
    for i in 0..n{
        index.entry(a[i]).or_insert(vec![]).push(i);
    }
    
    mov!(0);
    let mut ans=0;
    for _ in 1..n{
        let (w,d)=min.first().unwrap();
        ans+=w;
        let id=div_to_id[&d];
        let new=*que[id].co_que.last().unwrap();
        let idx=index.get_mut(&new).unwrap().pop().unwrap();
        mov!(idx);
    }
    
    println!("{ans}");
}



#[macro_export]
macro_rules! cap{
    ()=>{};
    (#![] $($fn:tt)*)=>{
        cap!([],[],[],[],[$($fn)*],[],[]);
    };
    (#![$($g:tt)*] $($fn:tt)*)=>{
        cap!([$($g)*,],[],[],[],[$($fn)*],[],[]);
    };
    ([$name:ident:$t:ty,$($rem:tt)*],[$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[$($fn:tt)*],[],[])=>{
        cap!([$($rem)*],[$name:$t,$($ga)*],[$name,$($gn)*],[$name,$($ge)*],[$($fn)*],[],[]);
    };
    ([$($flag:tt)? $name:ident:$t:ty,$($rem:tt)*],[$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[$($fn:tt)*],[],[])=>{
        cap!([$($rem)*],[$name:$($flag)?$t,$($ga)*],[$name,$($gn)*],[$($flag)?$name,$($ge)*],[$($fn)*],[],[]);
    };
    ([&mut $name:ident:$t:ty,$($rem:tt)*],[$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[$($fn:tt)*],[],[])=>{
        cap!([$($rem)*],[$name:&mut $t,$($ga)*],[$name,$($gn)*],[&mut $name,$($ge)*],[$($fn)*],[],[]);
    };
    ([],[$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[$(#[$($att:tt)*])? fn $name:ident($($arg:tt)*) $body:block $($rem:tt)*],[$($info:tt)*],[$($fn:tt)*])=>{
        cap!([],[$($ga)*],[$($gn)*],[$($ge)*],[$($rem)*],[(($(#[$($att)*])?),$name,($($arg)*),(),$body),$($info)*],[$name,$($fn)*]);
    };
    ([],[$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[$(#[$($att:tt)*])? fn $name:ident($($arg:tt)*)->$ret:ty $body:block $($rem:tt)*],[$($info:tt)*],[$($fn:tt)*])=>{
        cap!([],[$($ga)*],[$($gn)*],[$($ge)*],[$($rem)*],[(($(#[$($att)*])?),$name,($($arg)*),$ret,$body),$($info)*],[$name,$($fn)*]);
    };
    ([],[$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[],[$($info:tt)*],[$($fn:tt)*])=>{
        cap!(@make_fn [$($ga)*],[$($gn)*],[$($ge)*],[$($info)*],[$($fn)*]);
    };
    (@make_fn [$($ga:ident:$gt:ty,)*],[$($gn:tt)*],[$($ge:tt)*],[(($($att:tt)*),$name:ident,($($arg:tt)*),$ret:ty,$body:block),$($rem:tt)*],[$($fn:tt)*])=>{
        $($att)*
        fn $name($($ga:$gt,)*$($arg)*)->$ret{
            $(#[allow(unused_variables)] let $ga=$ga;)*
            cap!(@make_macros ($),[$($gn)*],[$($fn)*]);
            $body
        }
        cap!(@make_fn [$($ga:$gt,)*],[$($gn)*],[$($ge)*],[$($rem)*],[$($fn)*]);
    };
    (@make_fn [$($ga:tt)*],[$($gn:tt)*],[$($ge:tt)*],[],[$($fn:tt)*])=>{
        cap!(@make_global_macros ($),[$($ge)*],[$($fn)*]);
    };
    (@make_macros ($dol:tt),[$($gn:ident,)*],[$name:ident,$($rem:tt)*])=>{
        #[allow(unused_macros)]
        macro_rules! $name{
            ($dol($dol arg:expr),*)=>{$name($($gn,)* $dol($dol arg),*)}
        }
        cap!(@make_macros ($),[$($gn,)*],[$($rem)*]);
    };
    (@make_macros ($dol:tt),[$($gn:ident,)*],[])=>{};
    (@make_global_macros ($dol:tt),[$($ge:expr,)*],[$name:ident,$($rem:tt)*])=>{
        #[allow(unused_macros)]
        macro_rules! $name{
            ($dol($dol arg:expr),*)=>{$name($($ge,)* $dol($dol arg),*)}
        }
        cap!(@make_global_macros ($),[$($ge,)*],[$($rem)*]);
    };
    (@make_global_macros ($dol:tt),[$($ge:expr,)*],[])=>{};
}



mod rustc_hash{
    use core::convert::TryInto;
    use core::default::Default;
    use core::hash::BuildHasherDefault;
    use core::hash::Hasher;
    use core::mem::size_of;
    use core::ops::BitXor;
    use std::collections::{HashMap, HashSet};

    pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
    pub type FxHashSet<V> = HashSet<V, BuildHasherDefault<FxHasher>>;

    pub struct FxHasher {
        hash: usize,
    }

    #[cfg(target_pointer_width = "32")]
    const K: usize = 0x9e3779b9;
    #[cfg(target_pointer_width = "64")]
    const K: usize = 0x517cc1b727220a95;

    impl Default for FxHasher {
        #[inline]
        fn default() -> FxHasher {
            FxHasher { hash: 0 }
        }
    }

    impl FxHasher {
        #[inline]
        fn add_to_hash(&mut self, i: usize) {
            self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K);
        }
    }

    impl Hasher for FxHasher {
        #[inline]
        fn write(&mut self, mut bytes: &[u8]) {
            #[cfg(target_pointer_width = "32")]
            let read_usize = |bytes: &[u8]| u32::from_ne_bytes(bytes[..4].try_into().unwrap());
            #[cfg(target_pointer_width = "64")]
            let read_usize = |bytes: &[u8]| u64::from_ne_bytes(bytes[..8].try_into().unwrap());

            let mut hash = FxHasher { hash: self.hash };
            assert!(size_of::<usize>() <= 8);
            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.len() >= 1 {
                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);
        }

        #[cfg(target_pointer_width = "32")]
        #[inline]
        fn write_u64(&mut self, i: u64) {
            self.add_to_hash(i as usize);
            self.add_to_hash((i >> 32) as usize);
        }

        #[cfg(target_pointer_width = "64")]
        #[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
        }
    }
}
0