結果

問題 No.283 スライドパズルと魔方陣
コンテスト
ユーザー vwxyz
提出日時 2023-07-14 14:35:49
言語 Python3
(3.13.1 + numpy 2.2.1 + scipy 1.14.1)
結果
WA  
実行時間 -
コード長 8,183 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 244 ms
コンパイル使用メモリ 13,568 KB
実行使用メモリ 13,184 KB
最終ジャッジ日時 2024-09-15 23:36:52
合計ジャッジ時間 6,550 ms
ジャッジサーバーID
(参考情報)
judge4 / judge6
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 25 WA * 14
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

import bisect
import copy
import decimal
import fractions
import heapq
import itertools
import math
import random
import sys
import time
from collections import Counter,deque,defaultdict
from functools import lru_cache,reduce
from heapq import heappush,heappop,heapify,heappushpop,_heappop_max,_heapify_max
def _heappush_max(heap,item):
    heap.append(item)
    heapq._siftdown_max(heap, 0, len(heap)-1)
def _heappushpop_max(heap, item):
    if heap and item < heap[0]:
        item, heap[0] = heap[0], item
        heapq._siftup_max(heap, 0)
    return item
from math import gcd as GCD
read=sys.stdin.read
readline=sys.stdin.readline
readlines=sys.stdin.readlines
write=sys.stdout.write

def Magic_Circle(N):
    if N==2:
        magic_cycle=None
    elif N%4==0:
        magic_cycle=[[None]*N for x in range(N)]
        for x in range(N):
            for y in range(N):
                if (x-y)%4==0 or (x+y)%4==3:
                    magic_cycle[x][y]=x*N+y
        for x in range(N-1,-1,-1):
            for y in range(N-1,-1,-1):
                if magic_cycle[x][y]==None:
                    magic_cycle[x][y]=(N-1-x)*N+(N-1-y)
    elif N%4==2:
        n=N//2
        magic_cycle=[[None]*N for x in range(N)]
        mc=Magic_Circle(n)
        L=[[3,0],[1,2]]
        U=[[0,3],[1,2]]
        X=[[0,3],[2,1]]
        for x in range(n):
            for y in range(n):
                if n//2+1<x:
                    LUX=X
                elif x==n//2+1 and y!=n//2 or (x,y)==(n//2,n//2):
                    LUX=U
                else:
                    LUX=L
                for i in range(2):
                    for j in range(2):
                        magic_cycle[x*2+i][y*2+j]=mc[x][y]*4+LUX[i][j]
    else:
        n=N//2
        magic_cycle=[[None]*N for i in range(N)]
        for i in range(N):
            for j in range(N):
                magic_cycle[(i+j-n)%N][(-i+j+n)%N]=i*N+j
    return magic_cycle

class Segment_Tree:
    def __init__(self,N,f,e,lst=None,dynamic=False):
        self.f=f
        self.e=e
        self.N=N
        if dynamic:
            self.segment_tree=defaultdict(lambda:self.e)
        else:
            if lst==None:
                self.segment_tree=[self.e]*2*self.N
            else:
                assert len(lst)<=self.N
                self.segment_tree=[self.e]*self.N+[x for x in lst]+[self.e]*(N-len(lst))
                for i in range(self.N-1,0,-1):
                    self.segment_tree[i]=self.f(self.segment_tree[i<<1],self.segment_tree[i<<1|1])

    def __getitem__(self,i):
        if type(i)==int:
            if -self.N<=i<0:
                return self.segment_tree[i+self.N*2]
            elif 0<=i<self.N:
                return self.segment_tree[i+self.N]
            else:
                raise IndexError("list index out of range")
        else:
            a,b,c=i.start,i.stop,i.step
            if a==None:
                a=self.N
            else:
                a+=self.N
            if b==None:
                b=self.N*2
            else:
                b+=self.N
            return self.segment_tree[slice(a,b,c)]

    def __setitem__(self,i,x):
        if -self.N<=i<0:
            i+=self.N*2
        elif 0<=i<self.N:
            i+=self.N
        else:
            raise IndexError("list index out of range")
        self.segment_tree[i]=x
        while i>1:
            i>>= 1
            self.segment_tree[i]=self.f(self.segment_tree[i<<1],self.segment_tree[i<<1|1])

    def Build(self,lst):
        for i,x in enumerate(lst,self.N):
            self.segment_tree[i]=x
        for i in range(self.N-1,0,-1):
            self.segment_tree[i]=self.f(self.segment_tree[i<<1],self.segment_tree[i<<1|1])

    def Fold(self,L=None,R=None):
        if L==None:
            L=self.N
        else:
            L+=self.N
        if R==None:
            R=self.N*2
        else:
            R+=self.N
        vL=self.e
        vR=self.e
        while L<R:
            if L&1:
                vL=self.f(vL,self.segment_tree[L])
                L+=1
            if R&1:
                R-=1
                vR=self.f(self.segment_tree[R],vR)
            L>>=1
            R>>=1
        return self.f(vL,vR)

    def Fold_Index(self,L=None,R=None):
        if L==None:
            L=self.N
        else:
            L+=self.N
        if R==None:
            R=self.N*2
        else:
            R+=self.N
        if L==R:
            return None
        x=self.Fold(L-self.N,R-self.N)
        while L<R:
            if L&1:
                if self.segment_tree[L]==x:
                    i=L
                    break
                L+=1
            if R&1:
                R-=1
                if self.segment_tree[R]==x:
                    i=R
                    break
            L>>=1
            R>>=1
        while i<self.N:
            if self.segment_tree[i]==self.segment_tree[i<<1]:
                i<<=1
            else:
                i<<=1
                i|=1
        i-=self.N
        return i

    def Bisect_Right(self,L=None,f=None):
        if L==self.N:
            return self.N
        if L==None:
            L=0
        L+=self.N
        vl=self.e
        vr=self.e
        l,r=L,self.N*2
        while l<r:
            if l&1:
                vl=self.f(vl,self.segment_tree[l])
                l+=1
            if r&1:
                r-=1
                vr=self.f(self.segment_tree[r],vr)
            l>>=1
            r>>=1
        if f(self.f(vl,vr)):
            return self.N
        v=self.e
        while True:
            while L%2==0:
                L>>=1
            vv=self.f(v,self.segment_tree[L])
            if f(vv):
                v=vv
                L+=1
            else:
                while L<self.N:
                    L<<=1
                    vv=self.f(v,self.segment_tree[L])
                    if f(vv):
                        v=vv
                        L+=1
                return L-self.N

    def Bisect_Left(self,R=None,f=None):
        if R==0:
            return 0
        if R==None:
            R=self.N
        R+=self.N
        vl=self.e
        vr=self.e
        l,r=self.N,R
        while l<r:
            if l&1:
                vl=self.f(vl,self.segment_tree[l])
                l+=1
            if r&1:
                r-=1
                vr=self.f(self.segment_tree[r],vr)
            l>>=1
            r>>=1
        if f(self.f(vl,vr)):
            return 0
        v=self.e
        while True:
            R-=1
            while R>1 and R%2:
                R>>=1
            vv=self.f(self.segment_tree[R],v)
            if f(vv):
                v=vv
            else:
                while R<self.N:
                    R=2*R+1
                    vv=self.f(self.segment_tree[R],v)
                    if f(vv):
                        v=vv
                        R-=1
                return R+1-self.N

    def __str__(self):
        return "["+", ".join(map(str,self.segment_tree[self.N:]))+"]"

def Inversion_Number(lst,weight=False,weakly=False):
    compress,decompress=Compress(lst)
    compressed_lst=[compress[x] for x in lst]
    N=len(compress)
    if not weight:
        weight=[1]*len(lst)
    ST=Segment_Tree(N,lambda x,y:x+y,0)
    inversion_number=0
    for c,x in zip(weight,compressed_lst):
        inversion_number+=ST.Fold(x if weakly else x+1,N)*c
        ST[x]+=c
    return inversion_number

def Compress(lst):
    decomp=sorted(list(set(lst)))
    comp={x:i for i,x in enumerate(decomp)}
    return comp,decomp

N=int(readline())
if N==2:
    print("impossible")
    exit()
bl=0
A=[list(map(int,readline().split())) for i in range(N)]
for i in range(N):
    for j in range(N):
        A[i][j]=(A[i][j]-1)%(N*N)+1
a=[]
for i in range(N):
    a+=A[i]
for i in range(N):
    for j in range(N):
        if A[i][j]==N*N:
            bl^=(i+j)%2
MC=Magic_Circle(N)
mc=[]
for i in range(N):
    mc+=MC[i]
for i in range(N):
    for j in range(N):
        if MC[i][j]==0:
            bl^=(i+j)%2
if bl^Inversion_Number(a)%2^Inversion_Number(mc)%2:
    if N%2==0:
        MC=MC[::-1]
    else:
        MC[0],MC[N-1]=MC[N-1],MC[0]
print("possible")
for i in range(N):
    print(*[x+1 for x in MC[i]])
0