結果

問題 No.5022 XOR Printer
ユーザー rhoo
提出日時 2025-07-26 16:32:16
言語 Rust
(1.83.0 + proconio)
結果
AC  
実行時間 603 ms / 2,000 ms
コード長 17,783 bytes
コンパイル時間 15,272 ms
コンパイル使用メモリ 397,208 KB
実行使用メモリ 7,720 KB
スコア 5,189,796,140
最終ジャッジ日時 2025-07-26 16:34:31
合計ジャッジ時間 45,681 ms
ジャッジサーバーID
(参考情報)
judge6 / judge5
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 50
権限があれば一括ダウンロードができます
コンパイルメッセージ
warning: unexpected `cfg` condition value: `local`
   --> src/main.rs:704:7
    |
704 | #[cfg(feature = "local")]
    |       ^^^^^^^^^^^^^^^^^ help: remove the condition
    |
    = note: no expected values for `feature`
    = help: consider adding `local` as a feature in `Cargo.toml`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default

warning: unexpected `cfg` condition value: `local`
   --> src/main.rs:706:11
    |
706 | #[cfg(not(feature = "local"))]
    |           ^^^^^^^^^^^^^^^^^ help: remove the condition
    |
    = note: no expected values for `feature`
    = help: consider adding `local` as a feature in `Cargo.toml`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration

warning: unexpected `cfg` condition value: `local`
   --> src/main.rs:486:15
    |
486 |         #[cfg(feature = "local")]{
    |               ^^^^^^^^^^^^^^^^^ help: remove the condition
    |
    = note: no expected values for `feature`
    = help: consider adding `local` as a feature in `Cargo.toml`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration

ソースコード

diff #

#![allow(unused_imports,non_snake_case,dead_code)]
use proconio::{marker::*,*};



fn main(){
    get_time();
    let mut a=get_input().clone();
    let mut n=0;

    let mut p=P::new(0,0);
    let r=P::new(0,0);
    let mut ans=vec![];

    let get=|a:u32,i:usize|->u32{
        a>>19-i&1
    };

    const K:usize=5;
    
    // step1
    let mut ps=vec![];
    for p in iterp(){
        if p!=r && get(a[p],0)==1{
            ps.push(p);
        }
    }
    let route=make_route(p,Some(r),&ps);
    for &np in &route[1..route.len()-1]{
        ans.extend(get_path(p,np));
        p=np;
        if get(n,0)==0{
            ans.push(Copy);
            n^=a[p];
        }
        ans.push(Write);
        a[p]^=n;
    }
    ans.extend(get_path(p,r));
    p=r;
    if get(a[r],0)==0{
        ans.push(Write);
        a[p]^=n;
    }
    ans.push(Copy);
    n^=a[p];

    // step2
    let mut skip=std::collections::HashSet::new();
    skip.insert(r);
    for i in 1..K{
        let mut ps=vec![];
        for p in iterp(){
            if !skip.contains(&p) && get(a[p],i)==1{
                ps.push(p);
            }
        }

        let mut route=make_route(p,None,&ps);
        for &p in &skip{
            if (p==r && get(a[p],i)==0) || (p!=r && get(a[p],i)==1){
                let arg=(2..route.len()).min_by_key(|&i|route[i-1].manh(p)+p.manh(route[i])).unwrap();
                route.insert(arg,p);
            }
        }

        for &np in &route[1..route.len()-1]{
            ans.extend(get_path(p,np));
            p=np;
            if get(n,i)==0{
                ans.push(Copy);
                n^=a[p];
            }
            ans.push(Write);
            a[p]^=n;
        }

        ans.extend(get_path(p,route[route.len()-1]));
        p=route[route.len()-1];
        skip.insert(p);
        ans.push(Copy);
        n^=a[p];
    }

    // step3
    let mut ps=vec![];
    for p in iterp(){
        if !skip.contains(&p) && get(a[p],K)==1{
            ps.push(p);
        }
    }

    let mut route=make_route(p,Some(r),&ps);
    route.pop().unwrap();
    for &p in &skip{
        if (p==r && get(a[p],K)==0) || (p!=r && get(a[p],K)==1){
            let arg=(2..route.len()).min_by_key(|&i|route[i-1].manh(p)+p.manh(route[i])).unwrap();
            route.insert(arg,p);
        }
    }

    for &np in &route[1..route.len()-1]{
        ans.extend(get_path(p,np));
        p=np;
        if get(n,K)==0{
            ans.push(Copy);
            n^=a[p];
        }
        ans.push(Write);
        a[p]^=n;
    }

    ans.extend(get_path(p,route[route.len()-1]));
    p=route[route.len()-1];
    skip.insert(p);
    ans.push(Copy);
    n^=a[p];

    ans.extend(get_path(p,r));
    p=r;
    ans.push(Copy);
    n^=a[p];

    // step4
    for i in 0..N{
        for _ in 1..N{
            if i%2==0{
                ans.push(R);
                ans.push(Write);
            } else{
                ans.push(L);
                ans.push(Write);
            }
        }
        if i!=N-1{
            ans.push(D);
            ans.push(Write);
        }
    }

    for p in iterp(){
        if p!=r{
            a[p]^=n;
        }
    }

    p=P::new(N-1,0);

    let np=iterp().min_by_key(|&p|a[p]).unwrap();
    ans.extend(get_path(p,np));
    p=np;
    ans.push(Write);
    a[p]^=n;
    ans.push(Copy);
    n^=a[p];
    ans.push(Write);
    a[p]^=n;

    for &a in &ans{
        let c=match a{
            U=>'U',
            D=>'D',
            L=>'L',
            R=>'R',
            Write=>'W',
            Copy=>'C',
        };
        println!("{c}");
    }

    let mut score=0;
    let mut res=[[0;N];N];
    for p in iterp(){
        score+=a[p] as u64;
        res[p]=a[p]>>(19-K);
    }

    eprintln!("score = {}",score);
    eprintln!("size = {}",ans.len());

    // debug!(res);
}



fn get_path(mut p:P,q:P)->Vec<Act>{
    let mut path=vec![];
    'a: while p!=q{
        for i in 0..DD.len(){
            let np=p+DD[i];
            if p.manh(q)>np.manh(q){
                path.push(DC[i]);
                p=np;
                continue 'a;
            }
        }
        panic!();
    }
    path
}



// s->gへのパスでpsをすべて通るようなやつ
// gがNoneのときはpsのどれかが最後
fn make_route(s:P,g:Option<P>,ps:&[P])->Vec<P>{
    const INF:i64=i64::MAX/10000;
    
    let si=ps.len();
    let gi=ps.len()+1;
    let mi=ps.len()+2;
    
    let get=|i:usize|if i==gi{g.unwrap()}else if i==si{s}else{ps[i]};
    let mut d=vec![vec![0;ps.len()+3];ps.len()+3];
    for i in 0..mi{
        for j in 0..mi{
            if g.is_none() && (i==gi || j==gi){
                continue;
            }
            d[i][j]=get(i).manh(get(j)) as i64;
        }
    }
    d[si][mi]=0;
    d[mi][si]=0;
    d[gi][mi]=0;
    d[mi][gi]=0;
    for i in 0..ps.len(){
        d[i][mi]=INF;
        d[mi][i]=INF;
    }

    // si,0..p,gi,mi,si
    let mut a=vec![si];
    a.extend(0..ps.len());
    a.push(gi);
    a.push(mi);
    a.push(si);

    let route=tsp(&d,&a,get_time()+0.1);
    assert!(route[1]==mi || route[route.len()-2]==mi);

    let route=if route[1]==mi{
        // si,mi,gi,0..p,si
        route[2..].iter().copied().rev().collect::<Vec<_>>()
    } else{
        route[..route.len()-2].iter().copied().collect::<Vec<_>>()
    };

    assert!(route[0]==si && route[route.len()-1]==gi);

    if g.is_none(){
        route[..route.len()-1].iter().map(|&i|get(i)).collect::<Vec<_>>()
    } else{
        route.iter().map(|&i|get(i)).collect::<Vec<_>>()
    }
}



#[derive(Clone,Copy)]
enum Act{
    U,D,L,R,
    Write,
    Copy,
}
use Act::*;
const DC:[Act;4]=[L,U,R,D];



pub fn compute_cost(g: &Vec<Vec<i64>>, ps: &Vec<usize>) -> i64 {
    let mut tmp = 0;
    for i in 0..ps.len() - 1 {
        tmp += g[ps[i]][ps[i + 1]];
    }
    tmp
}

// mv: (i, dir)
pub fn apply_move(tour: &mut Vec<usize>, idx: &mut Vec<usize>, mv: &[(usize, usize)]) {
    let k = mv.len();
    let mut ids: Vec<_> = (0..k).collect();
    ids.sort_by_key(|&i| mv[i].0);
    let mut order = vec![0; k];
    for i in 0..k {
        order[ids[i]] = i;
    }
    let mut tour2 = Vec::with_capacity(mv[ids[k - 1]].0 - mv[ids[0]].0);
    let mut i = ids[0];
    let mut dir = 0;
    loop {
        let (j, rev) = if dir == mv[i].1 {
            ((i + 1) % k, 0)
        } else {
            ((i + k - 1) % k, 1)
        };
        if mv[j].1 == rev {
            if order[j] == k - 1 {
                break;
            } else {
                i = ids[order[j] + 1];
                dir = 0;
                tour2.extend_from_slice(&tour[mv[j].0 + 1..mv[i].0 + 1]);
            }
        } else {
            i = ids[order[j] - 1];
            dir = 1;
            tour2.extend(tour[mv[i].0 + 1..mv[j].0 + 1].iter().rev().cloned());
        }
    }
    assert_eq!(tour2.len(), mv[ids[k - 1]].0 - mv[ids[0]].0);
    tour[mv[ids[0]].0 + 1..mv[ids[k - 1]].0 + 1].copy_from_slice(&tour2);
    for i in mv[ids[0]].0 + 1..mv[ids[k - 1]].0 + 1 {
        idx[tour[i]] = i;
    }
}

pub const FEASIBLE3: [bool; 64] = [false, false, false, true, false, true, true, true, true, true, true, false, true, false, false, false,
                                false, false, false, false, false, false, false, false, false, false, false, true, false, true, true, true,
                                true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false,
                                false, false, false, true, false, true, true, true, true, true, true, false, true, false, false, false];

pub fn tsp(g: &Vec<Vec<i64>>, qs: &Vec<usize>, until: f64) -> Vec<usize> {
    let n = g.len();
    let mut f = vec![vec![]; n];
    for i in 0..n {
        for j in 0..n {
            if i != j {
                f[i].push((g[i][j], j));
            }
        }
        f[i].sort_by(|&(a, _), &(b, _)| a.partial_cmp(&b).unwrap());
    }
    let mut ps = qs.clone();
    let mut idx = vec![!0; n];
    let (mut min, mut min_ps) = (compute_cost(&g, &qs), ps.clone());
    while get_time() < until {
        let mut cost = compute_cost(&g, &ps);
        for p in 0..n {
            idx[ps[p]] = p;
        }
        loop {
            let mut ok = false;
            for i in 0..n {
                for di in 0..2 {
                    'loop_ij: for &(ij, vj) in &f[ps[i + di]] {
                        if g[ps[i]][ps[i + 1]] - ij <= 0 {
                            break;
                        }
                        for dj in 0..2 {
                            let j = if idx[vj] == 0 && dj == 0 {
                                n - 1
                            } else {
                                idx[vj] - 1 + dj
                            };
                            let gain = g[ps[i]][ps[i + 1]] - ij + g[ps[j]][ps[j + 1]];
                            // 2-opt
                            if di != dj && gain - g[ps[j + dj]][ps[i + 1 - di]] > 0 {
                                cost -= gain - g[ps[j + dj]][ps[i + 1 - di]];
                                apply_move(&mut ps, &mut idx, &[(i, di), (j, dj)]);
                                ok = true;
                                break 'loop_ij;
                            }
                            // 3-opt
                            for &(jk, vk) in &f[ps[j + dj]] {
                                if gain - jk <= 0 {
                                    break;
                                }
                                for dk in 0..2 {
                                    let k = if idx[vk] == 0 && dk == 0 {
                                        n - 1
                                    } else {
                                        idx[vk] - 1 + dk
                                    };
                                    if i == k || j == k {
                                        continue;
                                    }
                                    let gain = gain - jk + g[ps[k]][ps[k + 1]];
                                    if gain - g[ps[k + dk]][ps[i + 1 - di]] > 0 {
                                        let mask = if i < j { 1 << 5 } else { 0 }
                                                | if i < k { 1 << 4 } else { 0 }
                                                | if j < k { 1 << 3 } else { 0 }
                                                | di << 2 | dj << 1 | dk;
                                        if FEASIBLE3[mask] {
                                            cost -= gain - g[ps[k + dk]][ps[i + 1 - di]];
                                            apply_move(&mut ps, &mut idx, &[(i, di), (j, dj), (k, dk)]);
                                            ok = true;
                                            break 'loop_ij;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if !ok {
                break;
            }
        }
        if min>cost{
            min=cost;
            min_ps = ps;
        }
        ps = min_ps.clone();
        if n <= 4 {
            break;
        }
        loop {
            if rnd::get(2) == 0 {
                // double bridge
                let mut is: Vec<_> = (0..4).map(|_| rnd::get(n)).collect();
                is.sort();
                if is[0] == is[1] || is[1] == is[2] || is[2] == is[3] {
                    continue;
                }
                ps = ps[0..is[0]+1].iter()
                        .chain(ps[is[2]+1..is[3]+1].iter())
                        .chain(ps[is[1]+1..is[2]+1].iter())
                        .chain(ps[is[0]+1..is[1]+1].iter())
                        .chain(ps[is[3]+1..].iter())
                        .cloned().collect();
            } else {
                for _ in 0..6 {
                    loop {
                        let i=rnd::range(1,n);
                        let j=rnd::range(1,n);
                        if i < j && j - i < n - 2 {
                            ps = ps[0..i].iter().chain(ps[i..j+1].iter().rev()).chain(ps[j+1..].iter()).cloned().collect();
                            break;
                        }
                    }
                }
            }
            break;
        }
    }
    min_ps
}


const N:usize=10;
const T:usize=1000;



static_data!{
    get_input:[[u32;N];N]|{
        input!{
            _n:usize,
            _t:usize,
            _a:[[u32;_n];_n],
        }
        let mut a=[[!0;N];N];
        for i in 0..N{
            a[i].copy_from_slice(&_a[i]);
        }
        a
    }
}



#[macro_export]
macro_rules! static_data{
    ($a:ident:$t:ty|$e:expr)=>{
        fn $a()->&'static $t{
            use std::sync::OnceLock;
            #[allow(non_upper_case_globals)]
            static $a:OnceLock<$t>=OnceLock::new();
            $a.get_or_init(||$e)
        }
    }
}



fn get_time()->f64{
    static mut START:f64=0.;
    let time=std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs_f64();
    unsafe{
        if START==0.{
            START=time;
        }

        #[cfg(feature = "local")]{
            return (time-START)*1.;
        }
        time-START
    }
}



#[allow(unused)]
mod rnd {
    static mut X2:u32=12345;
    static mut X3:u32=0xcafef00d;
    static mut C_X1:u64=0xd15ea5e5<<32|23456;

    pub fn next()->u32{
        unsafe{
            let x=X3 as u64*3487286589;
            let ret=(X3^X2)+(C_X1 as u32^(x>>32) as u32);
            X3=X2;
            X2=C_X1 as u32;
            C_X1=x+(C_X1>>32);
            ret
        }
    }

    pub fn next64()->u64{
        (next() as u64)<<32|next() as u64
    }

    pub fn nextf()->f64{
        unsafe{
            std::mem::transmute::<u64,f64>(0x3ff0000000000000|(next() as u64)<<20)-1.
        }
    }

    pub fn get(n:usize)->usize{
        assert!(0<n && n<=u32::MAX as usize);
        next() as usize*n>>32
    }

    pub fn range(a:usize,b:usize)->usize{
        assert!(a<b);
        get(b-a)+a
    }

    pub fn range_skip(a:usize,b:usize,skip:usize)->usize{
        assert!(a<=skip && skip<b);
        let n=range(a,b-1);
        n+(skip<=n) as usize
    }

    pub fn rangei(a:i64,b:i64)->i64{
        assert!(a<b);
        get((b-a) as usize) as i64+a
    }

    pub fn shuffle<T>(a:&mut [T]){
        for i in (0..a.len()).rev(){
            a.swap(i,get(i+1));
        }
    }

    pub fn shuffle_iter<T:Copy>(a:&mut [T])->impl Iterator<Item=T>+'_{
        (0..a.len()).rev().map(|i|{
            a.swap(i,get(i+1));
            a[i]
        })
    }
}


// trait RandomChoice{
//     type Output;
//     fn choice(&self)->Self::Output;
// }
// impl<T:Copy> RandomChoice for [T]{
//     type Output=T;
//     fn choice(&self)->T{
//         self[rnd::get(self.len())]
//     }
// }



// const DC:[char;4]=['L','U','R','D'];
const DD:[P;4]=[P{i:0,j:!0},P{i:!0,j:0},P{i:0,j:1},P{i:1,j:0}];
const DX:[P;8]=[P{i:0,j:!0},P{i:!0,j:!0},P{i:!0,j:0},P{i:!0,j:1},P{i:0,j:1},P{i:1,j:1},P{i:1,j:0},P{i:1,j:!0}];

const NULL:P=P{i:!0,j:!0};

#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Hash)]
struct P{
    i:usize,
    j:usize,
}
impl P{
    fn new(i:usize,j:usize)->P{
        P{i,j}
    }

    fn in_range(self,h:usize,w:usize)->bool{
        self.i<h && self.j<w
    }

    fn det(self,p:P)->i64{
        (self.i*p.j-self.j*p.i) as i64
    }

    fn dot(self,p:P)->i64{
        (self.i*p.i+self.j*p.j) as i64
    }

    fn abs2(self)->i64{
        self.dot(self)
    }
    
    fn manh(self,p:P)->usize{
        let abs_diff=|a,b|(a as i64-b as i64).abs() as usize;
        abs_diff(self.i,p.i)+abs_diff(self.j,p.j)
    }
}


impl std::fmt::Debug for P{
    fn fmt(&self,f:&mut std::fmt::Formatter)->std::fmt::Result{
        write!(f,"({}, {})",self.i,self.j)
    }
}


impl std::ops::Add for P{
    type Output=P;
    fn add(self,a:P)->P{
        P{
            i:self.i+a.i,
            j:self.j+a.j,
        }
    }
}
impl std::ops::Sub for P{
    type Output=P;
    fn sub(self,a:P)->P{
        P{
            i:self.i-a.i,
            j:self.j-a.j,
        }
    }
}
impl std::ops::Mul<usize> for P{
    type Output=P;
    fn mul(self,a:usize)->P{
        P{
            i:self.i*a,
            j:self.j*a,
        }
    }
}
impl std::ops::Div<usize> for P{
    type Output=P;
    fn div(self,a:usize)->P{
        P{
            i:self.i/a,
            j:self.j/a,
        }
    }
}
impl std::ops::Neg for P{
    type Output=P;
    fn neg(self)->P{
        P{
            i:self.i.wrapping_neg(),
            j:self.j.wrapping_neg(),
        }
    }
}


macro_rules! impl_p_ops{
    ($t:ty,$assign_trait:ident,$assign_func:ident,$op:tt)=>{
        impl std::ops::$assign_trait<$t> for P{
            fn $assign_func(&mut self,a:$t){
                *self=*self $ op a;
            }
        }
    }
}
impl_p_ops!(P,AddAssign,add_assign,+);
impl_p_ops!(P,SubAssign,sub_assign,-);
impl_p_ops!(usize,MulAssign,mul_assign,*);
impl_p_ops!(usize,DivAssign,div_assign,/);


macro_rules! impl_p_index{
    ($t:ty)=>{
        impl<T:std::ops::Index<usize>> std::ops::Index<P> for $t{
            type Output=T::Output;
            fn index(&self,idx:P)->&T::Output{
                &self[idx.i][idx.j]
            }
        }
        impl<T:std::ops::IndexMut<usize>> std::ops::IndexMut<P> for $t{
            fn index_mut(&mut self,idx:P)->&mut T::Output{
                &mut self[idx.i][idx.j]
            }
        }
    }
}
impl_p_index!([T]);
impl_p_index!(Vec<T>);



fn iterp()->impl Iterator<Item=P>{
    (0..N*N).map(|i|P::new(i/N,i%N))
}


#[cfg(feature = "local")]
include!("/home/akatsuti/cp/lib/debug_mod.rs");
#[cfg(not(feature = "local"))]
#[macro_export]macro_rules! debug{($($t:tt)*)=>{}}
0