Pertozavodsk Winter Training Camp 2016-Problem J. Sort It!

Time limit: 1.5 seconds
Memory limit: 512 mebibytes

You are given a permutation of length n: p1p_{1}, p2p_{2}, . . ., pnp_{n}. Consider some array of length n consisting of integers between 1 and n (equal elements are allowed). Let us transform the array in the following manner:
 at first, let us take all elements equal to p1 from it and write them on a piece of paper (if there are no such elements, just do not write anything). Then write all elements equal to p2p_{2}, then equal to p3p_{3}and so on, finishing by all elements equal to pn, thus obtaining a new array of length n. For example, if the permutation is 2 1 3 and the array is 2 3 2, the resulting array will be 2 2 3. If after this transformation we get a sorted array, let us call the original array sortable by p. Calculate the total number of arrays that are sortable by p.
As the answer can be very large, output it modulo 10910^{9} + 7.

input output
2 2
2 1
3 15
2 1 3

題意
按permutation所給的順序,將等長度只包含小於n的數組的對應值依次全部拿出來,如果最後的出來的是一個非減序的數組,則方案數加一
題解
先用樹狀數組求出permutation所有的遞增的子序列,用f[i]記錄,i表示長度爲i的子序列,f[]表示長度爲i的子序列的數目,這樣用res[i]表示對於一個n的數組只包含i個元素的總數,這樣就可以推出 res[i]= ini^{n} - j=1i1\sum_{j=1}^{i-1}(Cij_{i}^{j} *res[j]),總答案就是

  • i=1n\sum_{i=1}^{n}f[i] * res[i]
#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
 
const int maxn = 2e3+9;
const ll mod = 1e9+7;
 
 
int num[maxn],a[maxn];
ll f[maxn];
ll bit[maxn],cnt[maxn];
 
ll C[maxn][maxn];
 
ll res[maxn];
 
void getC(){
    C[0][0]=1;
    for(int i=1;i<=2000;i++){
        C[i][0]=1;
        for(int j=1;j<=i;j++){
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
    }
}
 
ll q_pow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
 
void add(int i,int x){
    while(i<=2000){
        bit[i]=(bit[i]+x)%mod;
        i+=(i&-i);
    }
}
 
ll query(int i){
    ll ans=0;
    while(i){
        ans=(ans+bit[i])%mod;
        i-=(i&-i);
    }
    return ans;
}
 
int main(){
    int n;
    scanf("%d",&n);
    getC();
//    for(int i=1;i<=10;i++){
//        for(int j=1;j<=i;j++){
//            printf("%d ",C[i][j]);
//        }
//        printf("\n");
//    }
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        num[a[i]]=1;
        cnt[a[i]]=1;
        f[1]++;
    }
    for(int i=2;i<=n;i++){
        memset(bit,0,sizeof(bit));
        for(int j=n;j>=1;j--){
            ll x=(query(2000)-query(a[j])+mod)%mod;
            if(num[a[j]]==i-1){
                add(a[j],cnt[a[j]]);
            }
            if(x>0){
                f[i]=(f[i]+x)%mod;
                cnt[a[j]]=x;
                num[a[j]]=i;
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=n;i++){
        res[i]=q_pow(i,n);
        for(int j=1;j<i;j++){
            res[i]=(res[i]-C[i][j]*res[j]%mod+mod)%mod;
        }
        ans=(ans+res[i]*f[i]%mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章