数列

来源:互联网 发布:小说软件汤圆类似 编辑:程序博客网 时间:2024/04/28 17:28

题目描述

有一个长度为n 的排列,现在有一些位置的数已经模糊不清了,你只知道这个排列的逆序对个数是K,你能计算出总共有多少可能的排列吗?

折半

很经典的meet in the middle
不说了,记住有各种精妙实现压复杂度。

#include<cstdio>#include<algorithm>#include<map>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=1000+10,mx=17297280+5;struct dong{    int x,y;} g[mx];int L[20000],R[20000],f[1000000+10];int a[maxn],b[20],c[20][20],d[20],e[20],pl[6000][20],coun[20000];bool bz[maxn];int i,j,k,l,r,t,n,m,top,tot,cnt,wdc;ll ans;void pp(int x,int lim){    int i;    if (x==lim+1){        ++cnt;        fo(i,1,lim) pl[cnt][i]=d[i];        return;    }    fo(i,1,lim)         if (!bz[i]){            bz[i]=1;            d[x]=i;            pp(x+1,lim);            bz[i]=0;        }}void dfs(int x,int y,int lim){    if (top-x+1<lim-y) return;    int i,j,k,t,s;    if (x==top+1){        fo(i,1,cnt){            fo(j,1,lim) e[pl[i][j]]=d[j];            t=0;            fo(j,1,lim) t+=c[l+j-1][e[j]];            s=0;            fo(j,1,lim){                t+=coun[s>>e[j]];                s+=1<<(e[j]-1);            }            /*zlt.x=s;zlt.y=t;            g[zlt]++;*/            g[++wdc].x=s;g[wdc].y=t;        }        return;    }    dfs(x+1,y,lim);    if (y<lim){        d[y+1]=x;        dfs(x+1,y+1,lim);    }}void dg(int x,int y,int lim){    if (top-x+1<lim-y) return;    int i,j,k,t,s;    if (x==top+1){        int S=0;        fo(i,1,lim) S+=1<<(d[i]-1);        S^=(1<<top)-1;        if (!L[S]) return;        fo(i,L[S],R[S]) f[g[i].y]++;        fo(i,1,cnt){            fo(j,1,lim) e[pl[i][j]]=d[j];            t=0;            fo(j,1,lim) t+=c[l+j-1][e[j]];            s=0;            fo(j,1,lim) s+=1<<(e[j]-1);            s^=(1<<top)-1;            fo(j,1,lim){                t+=coun[s>>e[j]];                s+=1<<(e[j]-1);            }            /*zlt.x=s;zlt.y=m-t;            ans+=(ll)g[zlt];*/            if (m-t<=1000000) ans+=(ll)f[m-t];        }        fo(i,L[S],R[S]) f[g[i].y]--;        return;    }    dg(x+1,y,lim);    if (y<lim){        d[y+1]=x;        dg(x+1,y+1,lim);    }}bool cmp(dong a,dong b){    return a.x<b.x;}int main(){    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,n){        scanf("%d",&a[i]);        if (a[i]) bz[a[i]]=1;    }    fo(i,1,n)        if (!bz[i]) b[++top]=i;    fo(i,1,n){        if (a[i]) continue;        ++tot;        fo(j,1,top)            fo(k,1,n)                if (a[k]){                    if (k<i&&a[k]>b[j]) c[tot][j]++;                    else if (k>i&&a[k]<b[j]) c[tot][j]++;                }    }    fo(i,1,n-1)        if (a[i])            fo(j,i+1,n)                if (a[j]&&a[i]>a[j]) m--;    fo(i,1,top/2) bz[i]=0;    pp(1,top/2);    fo(i,0,16383){        k=i;        while (k){            coun[i]++;            k-=(k&-k);        }    }    l=1;r=top/2;    dfs(1,0,top/2);    sort(g+1,g+wdc+1,cmp);    fo(i,1,wdc){        if (g[i].x!=g[i-1].x){            R[g[i-1].x]=i-1;            L[g[i].x]=i;        }    }    R[g[wdc].x]=wdc;    l=top/2+1;r=top;    cnt=0;    fo(i,1,top-top/2) bz[i]=0;    pp(1,top-top/2);    dg(1,0,top-top/2);    printf("%lld\n",ans);}
0 0
原创粉丝点击