一道数据结构题,求k阶逆序数

#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int maxn = 1e5+10;
const int mod = 1e9+7;
const int maxm = 12;
struct bt{
    int bitree[maxn];
    void init(){
        memset(bitree,0,sizeof(bitree));
    }
    int lowbit(int x){
        return x&(-x);
    }
    void add(int pos,int val){
        while(pos < maxn){
            bitree[pos] = (bitree[pos] + val) % mod;
            pos += lowbit(pos);
        }
    }
    int get(int pos){
        int sum = 0;
        while(pos){
            sum = (sum + bitree[pos])%mod;
            pos -= lowbit(pos);
        }
        return sum;
    }
}bts[maxm];
int n,k;
int mi[maxm][maxn];
int fac[maxm];
int inv[maxm];
int mod_pow(int x,int p,int mod)
{
       int ans = 1;
       while(p > 0)
       {
              if(p & 1)
                     ans = (x * ans)%mod;
              x = (x*x) % mod;
              p >>= 1;
       }
       return (ans + mod )% mod;
}
int mod_inverse_feima(int a,int m)
{
       int ans = mod_pow(a,m-2,m);
       return (ans + m)%mod;
}
int C(int n,int m){
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
void init(){
    for(int i = 0;i < maxn;++i) mi[0][i] = 1;
    for(int t = 1;t <= k;++t)
        for(int i = 0;i < maxn;++i)
            mi[t][i] = mi[t-1][i]*i%mod;

    inv[0] = fac[0] = 1;
    for(int i = 1;i < maxm;++i) fac[i] = fac[i-1]*i,inv[i] = mod_inverse_feima(fac[i],mod);
    for(int i = 0;i < maxm;++i) bts[i].init();
}
main(){
    cin>>n>>k;
    init();
    int ans = 0;
    for(int i = 1;i <= n;++i){
        int tmp;scanf("%lld",&tmp);
        for(int t = 0;t <= k;++t){
            int f = t%2?-1:1;
            ans = (ans + f*mi[k-t][i]*(bts[t].get(maxn-1) - bts[t].get(tmp))%mod*C(k,t) + mod)%mod;
        }
        for(int t = 0;t <= k;++t){
            bts[t].add(tmp,mi[t][i]);
        }
    }
    cout<<(ans + mod)%mod<<endl;
    return 0;
} 
/*
5 10
3 7 4 4 1

*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值