牛客 K-ary Heap

【牛客 K-ary Heap】题意:问你某一个k叉堆是 所有可能的k叉堆中的第几个
思路:枚举第一个大于原序列的位置,得到大于该排列的k叉堆的总数,再用总数减去即可。

#include using namespace std; typedef long long LL; typedef long long lint; typedef pair pii; const int maxn = 5005; int a[maxn],fa[maxn]; vector ve[maxn]; int sz[maxn]; lint res[maxn]; typedef long long ll; const ll oo=1000000007; ll frac[maxn], carf[maxn]; ll inv(ll x){ if (x==1) return 1; else return (oo-oo/x)*inv(oo%x)%oo; } LL ad( LL x,LL y ){ x += y; return x%oo; } LL mul( LL x,LL y ){ x *= y; return x%oo; } void init(){ frac[0]=1; for (int i=1; i<=5000; i++) frac[i]=frac[i-1]*i%oo; carf[5000]=inv(frac[5000]); for (int i=5000; i>=1; i--) carf[i-1]=carf[i]*i%oo; }ll C(int n, int m){ if (m>n) return 0; else return frac[n]*carf[n-m]%oo*carf[m]%oo; } void dfs( int x,int f ){ fa[x] = f; res[x] = 1; sz[x] = 1; for( inti = 0; i < ve[x].size(); i++ ){ int y = ve[x][i]; dfs(y,x); sz[x] += sz[y]; } int le = sz[x]-1; for( auto y:ve[x] ){ res[x] = mul( res[x],res[y]*C( le,sz[y] )%oo); le -= sz[y]; } } void init( int n ){ for( int i = 0; i <= n; i++ ) ve[i].clear(); } int b[maxn],n; int lowbit( int x ){ return x&-x; } void add( int x,int v ){ while(x<=n){ b[x] += v; x += lowbit(x); } } int ask( int x ){ int res = 0; while(x){ res += b[x]; x -= lowbit(x); } return res; } int query( int l,int r ){ if( l > r ) return 0; return ask(r) - ask(l-1); } void initb( int n ){ for( int i =0 ; i <= n; i++ ) b[i] = 0; for( int i = 2; i <= n; i++ ) add( i,1 ); } set se; LL ans = 0; int main(){ init(); int T,k; scanf("%d",&T); for( int tt = 1; tt <= T; tt++ ){ printf("Case #%d: ",tt); ans = 0; scanf("%d%d",&n,&k); init(n); for( int i = 0; i < n; i++ )scanf("%d",&a[i]); initb(n); se.clear(); for( int i = 0; i < n; i++ )for( int j = k*i+1; j <= min( k*i+k,n-1 ); j++ )ve[i].push_back(j); dfs(0,-1); for( auto x:ve[0] ) se.insert( pii( a[fa[x]],x ) ); for( int i = 1; i < n; i++ ){ LL re = 1; int sum = 0; se.erase( pii( a[fa[i]],i ) ); se.insert( pii( a[i],i ) ); for( auto p = se.rbegin(); p != se.rend(); p++ ){ int v = p->first; int x = p->second; int lef = query( v+1,n ); lef -= sum; LL c =C( lef,sz[x] ); re = re * c %oo * res[x]%oo; //ans += C( lef,sz[x] ) * res[x]%oo; sum += sz[x]; } ans = (ans + re)%oo; add( a[i] ,-1); se.erase( pii( a[i],i ) ); for( auto x : ve[i] ){ se.insert( pii( a[i],x ) ); } } LL ans0 = (res[0] - ans + oo)%oo; printf("%lld\n",ans0); } return 0; }


    推荐阅读