zoukankan      html  css  js  c++  java
  • 计数 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();
    }
    
  • 相关阅读:
    python中的运算符的分类以及使用方法
    python的变量的命名规则以及定义
    C#和Java在重写上的区别
    IIS6 伪静态
    【读书笔记】Linux源码注释
    计算机是如何启动的?
    XSHELL下直接下载文件到本地(Windows)
    [转载]Linux 环境下编译 0.11版本内核 kernel
    虚拟化技术
    CentOS 6.4 编译安装LLVM3.3,Clang和Libc++
  • 原文地址:https://www.cnblogs.com/foreverpiano/p/luggu4223.html
Copyright © 2011-2022 走看看