计数 luogu 4223 期望逆序对

https://www.luogu.org/problemnew/show/P4223

期望乘以(inom {n}{2}^k)变成了计数问题

我们考虑每一组数((A, B))产生的贡献CCCCCACCCCBCCCC

分7组考虑((A, B))(k)次操作之后去哪里了

((A, B); (A, C);(B,A);(B,C);(C,A);(C,B);(C,C))

可以列出一个(7 imes 7)的矩阵表

矩阵快速幂后表示转移(k)次之后的系数(有点恶心

有一个结论就是CCCACCCBCCC

对于比如((A, C))这个状态

(B)到达(A)左边和到达(B)右边的方案数是和(C)的个数成正比的

数学归纳法可证

因此推出式子可以发现(i)(j>i)的贡献是一样的

树状数组维护即可

复杂度(mathcal O(nlog n))

#include <bits/stdc++.h>
#define int long long
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "
"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
  x = 0;char c = getchar(); bool f = 0;
  for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
  for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
  if(f) x = -x;
}
const int N = 5e5 + 233;
namespace {
  const int mo = 1e9 + 7;
  inline int add(int u, int v) {
    if((u += v) >= mo) u -= mo;
    return u;
  }
  inline int sub(int u, int v) {
    if((u -= v) < 0) u += mo;
    return u;
  }
  inline int mul(int u, int v) {
    return u * v % mo;
  }
  inline int pw(int a, int k, int mo) {
    int ans = 1;
    for(; k; k >>= 1, a = mul(a, a))
      if(k & 1) ans = mul(ans, a);
    return ans;
  }
}
struct Mar {
  int m[7][7];
  Mar() {
    memset(m, 0, sizeof m);
  }
  inline void E(void) {
    for(int i = 0; i < 7; i ++)
      m[i][i] = 1;
  }
}f, ans;
int a[N];
int cnt = 0, n, K;
Mar operator * (Mar a, Mar b) {
  Mar c;
  for(int i = 0; i < 7; i ++)
    for(int j = 0; j < 7; j ++) {
      int t = 0;
      for(int k = 0; k < 7; k ++)
        t = add(t, mul(a.m[i][k], b.m[k][j]));
      c.m[i][j] = t;
    }
  return c;
}

inline void I(int a, int b, int c, int d, int e, int g, int h) {
  f.m[cnt][0] = a; f.m[cnt][1] = b; f.m[cnt][2] = c;
  f.m[cnt][3] = d; f.m[cnt][4] = e; f.m[cnt][5] = g;
  f.m[cnt][6] = h;
  cnt ++;
}

inline void Matrix_Init(void) {
  int t = (n - 2) * (n - 3) / 2 % mo;
  I(t, n - 2, 1, 0, 0, n - 2, 0);
  I(1, t + n - 3, 0, 1, 1, 0, n - 3);
  I(1, 0, t, n - 2, n - 2, 0, 0);
  I(0, 1, 1, t + n - 3, 0, 1, n - 3);
  I(0, 1, 1, 0, t + n - 3, 1, n - 3);
  I(1, 0, 0, 1, 1, t + n - 3, n - 3);
  I(0, 1, 0, 1, 1, 1, t + 2 * (n - 4) + 1);
}

inline Mar mf(Mar a, int k) {
  Mar ans; ans.E();
  for(; k; k >>= 1, a = a * a)
    if(k & 1) ans = ans * a;
  return ans;
}

struct Bit {
  int tr[N], n;
  inline void init(void) {
    memset(tr, 0, sizeof tr);
    n = ::n;
  }
  inline void A(int u, int val) {
    for(; u <= n; u += u & -u)
      tr[u] = add(tr[u], val);
  }
  inline int Q(int u) {
    int ans = 0;
    for(; u >= 1; u -= u & -u)
      ans = add(ans, tr[u]);
    return ans;
  }
}x, y, z;

inline void doit(void) {
  x.init(); y.init(); z.init();
  int p = pw(n - 2, mo - 2, mo);
  int inv2 = pw(2, mo - 2, mo);
  int res = mul(n * (n - 1) / 2 % mo, ans.m[0][6]);
  res = mul(res, inv2);
  for(int j = 1; j <= n; j ++) {
    int t;
    int sm = x.Q(a[j] - 1);
    int la = j - 1 - sm;
    int p1 = add(mul(ans.m[0][3], mul(n - j, p)), mul(ans.m[0][5], mul(j - 2, p)));
    int p2 = add(mul(ans.m[0][3], mul(j - 2, p)), mul(ans.m[0][5], mul(n - j, p)));
    res = add(res, add(mul(la, p1), mul(sm, p2)));

    res = add(res, add(mul(la, ans.m[0][0]),
                       mul(sm, ans.m[0][2])));
    res = add(res, add(sub(y.Q(n), y.Q(a[j])), z.Q(a[j] - 1)));
    
    x.A(a[j], 1);

    t = add(mul(ans.m[0][1], mul(n - j - 1, p)),
            mul(ans.m[0][4], mul(j - 1, p)));
    y.A(a[j], t);
    
    t = add(mul(ans.m[0][1], mul(j - 1, p)),
            mul(ans.m[0][4], mul(n - j - 1, p)));
    z.A(a[j], t);
  }
  cout << res << "
";
}

main(void) {
  read(n); read(K);
  fo(i, n) read(a[i]);
  Matrix_Init();
  ans = mf(f, K);
  doit();
}
原文地址:https://www.cnblogs.com/foreverpiano/p/luggu4223.html