3990: [SDOI2015] Sort
Time limit:20 Sec Memory limit:128 MB
submit:152 solved:83
[Submit] [Status] [Discuss]
Description
Small A has a 1-2^n arrangement a[1..2^n], he wants to order a array from small to large, small a can perform operations have N, each operation can be executed at most once, for all I (1<=i<=n), I action is to divide the sequence from left to right into 2^{n-i+1} Segment, each paragraph exactly includes the number of 2^{i-1}, and then the overall exchange of two segments. Little A would like to know how many different sequences of operations can be ordered from small to large, and small a considers that the two sequence of operations are different when and only if the number of operations is different, or at least one operation is different (different or different in operation).
Here is an example of an operation:
n=3,a[1..8]=[3,6,1,2,7,8,5,4].
First operation, performing a 3rd operation, swapping a[1..4] and a[5..8], a[1..8 after Exchange] is [7,8,5,4,3,6,1,2].
The second operation, performing a 1th operation, swapping a[3] and a[5], a[1..8 after Exchange] is [7,8,3,4,5,6,1,2].
Third operation, perform 2nd operation, Exchange a[1..2] and a[7..8], a[1..8 after Exchange] is [1,2,3,4,5,6,7,8].
Input
First line, an integer n
Second line, 2^n Integer, A[1..2^n]
Output
An integer representing the answer
Sample Input
3
7 8 5 6 1 2 4 3
Sample Output
6
HINT
100% of the data, 1<=n<=12.
Source
Round 1 thanks to Zky for making unofficial data
Thinking problem + explosion search.
You can see that the order in which you use the action has no effect on the answer, so we can i A smaller start enumeration, and the final calculation of the contribution to the answer when factorial.
Small to large enumeration i The words would have a magical nature:
In i Each section of the operation is divided into 2 i? 1 Number, then we'll divide each field 2 i Number, if more than two paragraphs are not small to large and continuous numbers, there is no solution.
Because each exchange can only make two paragraphs orderly.
So Dfs simply enumerates how to exchange them.
(Note in completing i After the operation of Dfs, the length of the partition is 2 i The segments are incremented and continuous because the i + 1 And after the operation can only exchange larger blocks, so the small block must be in the previous exchange in order)
#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#define LL Long Longusing namespace STD; LL ans=0, fac[ -];intv[ -],a[100005],n,n;intOkintXintY) { for(inti=x+1; i<=y;i++)if(a[i]!=a[i-1]+1)return 0;return 1;}voidSwap (intXintYintL) { for(intI=0; i<l;i++) swap (a[x+i],a[y+i]);}voidDfsintIintCNT) {if(i==n) {ans+=fac[cnt];return; }intb[5],tot=0; for(intj=0; j<n;j+= (1<< (i+1)))if(!ok (j,j+ (1<< (i+1))-1)) {if(tot==4)return; b[++tot]=j,b[++tot]=j+ (1<<i); }if(!tot) DFS (i+1, CNT);if(tot==2) {if(a[b[2]]+(1<<i) ==a[b[1]]) {Swap (b[1],b[2],1<<i); DFS (i+1, cnt+1); Swap (b[1],b[2],1<<i); } }if(tot==4) {if(a[b[3]]+(1<<i) ==a[b[2]]&&a[b[1]]+(1<<i) ==a[b[4]]) {Swap (b[1],b[3],1<<i); DFS (i+1, cnt+1); Swap (b[1],b[3],1<<i); }if(a[b[3]]+(1<<i) ==a[b[1]]&&a[b[4]]+(1<<i) ==a[b[2]]) {Swap (b[1],b[4],1<<i); DFS (i+1, cnt+1); Swap (b[1],b[4],1<<i); }if(a[b[2]]+(1<<i) ==a[b[4]]&&a[b[1]]+(1<<i) ==a[b[3]]) {Swap (b[2],b[3],1<<i); DFS (i+1, cnt+1); Swap (b[2],b[3],1<<i); }if(a[b[1]]+(1<<i) ==a[b[4]]&&a[b[3]]+(1<<i) ==a[b[2]]) {Swap (b[2],b[4],1<<i); DFS (i+1, cnt+1); Swap (b[2],b[4],1<<i); } }}intMain () {Cin>>n; fac[0]=1; for(intI=1; i<=n;i++) fac[i]=1Ll*fac[i-1]*i; n=1<<n; for(intI=0; i<n;i++)scanf("%d", &a[i]); Dfs0,0);cout<<ans<<endl;return 0;}
"Bzoj 3990" [SDOI2015] Sort