#include <cstdio> //#define DEBUG 1 /* * Zadanie: per * Autor rozwiązania: Jan Horodecki */ int l_inwersji; void zmien(int i, int x, int drzewo[]){ while(i>0){ drzewo[i]+=x; i/=2; } } int mniejszeniz(int i,int drzewo[]){ int wyn=0; while(i!=1){ if(i%2==1){ wyn+=drzewo[i-1]; } i/=2; } return wyn; } long long znajdz(int pos,long long up_sumk,int inw,int n, long long k,int drzewo[],int drz_s){ // #ifdef DEBUG // for(int i=0;i<pos;i++)printf(" "); // printf("pos=%d up_sumk=%lld inw=%d n=%d k=%lld drz_s=%d ",pos,up_sumk,inw,n,k,drz_s); // for (int i=drz_s;i<2*drz_s;i++){ // printf("%d ",drzewo[i]); // } // printf("\n"); //#endif long long sumk=0; if(pos==n){ if(inw==l_inwersji){ //#ifdef DEBUG // printf("%lld +1 \n",up_sumk); //#endif if(up_sumk+1==k)return -1; return 1; } } //optymalizacje if(true){ if(inw>l_inwersji)return 0; int q=n-pos; if(inw+q*(q-1)/2<l_inwersji)return 0; } //koniec opt for(int i=drz_s ; i<drz_s+n; i++){ if(drzewo[i]==0){ zmien(i,1,drzewo); int akt_inw=inw; akt_inw+=i-drz_s-mniejszeniz(i,drzewo); int zwr=znajdz(pos+1,up_sumk+sumk,akt_inw,n,k,drzewo,drz_s); if(zwr==-1){ drzewo[pos]=i-drz_s+1; return -1; } sumk+=zwr; zmien(i,-1,drzewo); } } return sumk; } int main(){ int drzewo[524290]={},n,d_s=1; long long k; scanf("%d%lld",&n,&k); if( (n*(n-1)/2) %2 == 1 ){ printf("NIE"); return 0; } l_inwersji=n*(n-1)/4; while(d_s<n){ d_s=d_s<<1; } if(znajdz(0,0,0,n,k,drzewo,d_s)==-1){ printf("TAK\n"); for(int i=0;i<n;i++){ printf("%d ",drzewo[i]); } }else{ printf("NIE"); } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include <cstdio> //#define DEBUG 1 /* * Zadanie: per * Autor rozwiązania: Jan Horodecki */ int l_inwersji; void zmien(int i, int x, int drzewo[]){ while(i>0){ drzewo[i]+=x; i/=2; } } int mniejszeniz(int i,int drzewo[]){ int wyn=0; while(i!=1){ if(i%2==1){ wyn+=drzewo[i-1]; } i/=2; } return wyn; } long long znajdz(int pos,long long up_sumk,int inw,int n, long long k,int drzewo[],int drz_s){ // #ifdef DEBUG // for(int i=0;i<pos;i++)printf(" "); // printf("pos=%d up_sumk=%lld inw=%d n=%d k=%lld drz_s=%d ",pos,up_sumk,inw,n,k,drz_s); // for (int i=drz_s;i<2*drz_s;i++){ // printf("%d ",drzewo[i]); // } // printf("\n"); //#endif long long sumk=0; if(pos==n){ if(inw==l_inwersji){ //#ifdef DEBUG // printf("%lld +1 \n",up_sumk); //#endif if(up_sumk+1==k)return -1; return 1; } } //optymalizacje if(true){ if(inw>l_inwersji)return 0; int q=n-pos; if(inw+q*(q-1)/2<l_inwersji)return 0; } //koniec opt for(int i=drz_s ; i<drz_s+n; i++){ if(drzewo[i]==0){ zmien(i,1,drzewo); int akt_inw=inw; akt_inw+=i-drz_s-mniejszeniz(i,drzewo); int zwr=znajdz(pos+1,up_sumk+sumk,akt_inw,n,k,drzewo,drz_s); if(zwr==-1){ drzewo[pos]=i-drz_s+1; return -1; } sumk+=zwr; zmien(i,-1,drzewo); } } return sumk; } int main(){ int drzewo[524290]={},n,d_s=1; long long k; scanf("%d%lld",&n,&k); if( (n*(n-1)/2) %2 == 1 ){ printf("NIE"); return 0; } l_inwersji=n*(n-1)/4; while(d_s<n){ d_s=d_s<<1; } if(znajdz(0,0,0,n,k,drzewo,d_s)==-1){ printf("TAK\n"); for(int i=0;i<n;i++){ printf("%d ",drzewo[i]); } }else{ printf("NIE"); } return 0; } |