• #575. 「LibreOJ NOI Round #2」不等关系


    题目链接

    首先只考虑 < 的限制,即 > 可以大于也可以小于,那么实际上就是把序列分成几个递增序列,直接多重集排列即可。

    现在考虑 > 的限制。设 (f_i) 表示前 (i) 个的答案,那么我们先不管最后一个 > 的限制求个方案数,然后我们多算了那个 > 实际填 < 的情况,那么我们需要减去把那个 > 当成 < 的方案。但是我们减这个方案的时候还会多减一些,需要把前面的前面的那个 > 当成 < 的情况加上...

    [Large f_i = sum_{j=0}^{i-1}[s_j='>']f_j{i choose j}(-1)^{sum_{k=j+1}^i[s_k='>']} ]

    拆开组合数以后就可以分治 NTT 了。

    这题主要神仙在选取一个“标准点”——最后一个 > 是否合法,然后就是一直推下去了。

    关键代码:

    inline int cc(int x) { return x & 1 ? -1 : 1; }
    
    ll A[N], B[N];
    ll f[N], g[N], h[N];
    void sol(int L, int R) {
      if (!R) return ;
      if (L == R)	return f[L] = f[L] * cc(cnt[L - 1]) * jie[L] % P, h[L] = (s[L] == '>') * f[L] * cc(cnt[L]) * jieni[L] % P, void();
      int mid = (L + R) >> 1;
      sol(L, mid);
    
      int len = (R - L + 1); 
      for (register int i = 0; i < len; ++i)  A[i] = g[i];
      for (register int i = 0; i <= mid - L; ++i) B[i] = h[i + L]; 
    
      len += (mid - L + 1); 
      int limi = 1, Len = 0;
      while (limi <= len) limi <<= 1, ++Len;
      for (register int i = 0; i < limi; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (Len - 1));
      ntt(A, 1, limi), ntt(B, 1, limi);
      for (register int i = 0; i < limi; ++i) A[i] = A[i] * B[i] % P, B[i] = 0;
      ntt(A, -1, limi);
      for (register int i = mid + 1; i <= R; ++i) f[i] = (f[i] + A[i - L]) % P;
    
      for (register int i = 0; i <= limi; ++i)  A[i] = 0;
    
      sol(mid + 1, R); 
    }
    int main() {
      scanf("%s", s + 1); n = strlen(s + 1) + 1;
      s[0] = '>'; cnt[0] = 1;
      for (register int i = 1; i <= n; ++i) cnt[i] = cnt[i - 1] + (s[i] == '>');
      init();
      f[0] = 1; h[0] = -1;
      for (register int i = 1; i <= n; ++i) g[i] = jieni[i];
      sol(0, n); 
      printf("%lld
    ", (f[n] % P + P) % P);
      return 0;
    }
    
  • 相关阅读:
    mysql慢查询日志
    VS中MFC连接MySQL的方法【转】
    localtime函数时区问题
    gethostbyname()函数【转】
    剪切板操作
    C/C++字符串查找函数 【转】
    vs2013出现IntelliSense错误,但是错误又不影响使用的消除办法
    c语言基础精讲加实例(个人觉得复习基础挺好的,)
    vs2013下qt工程调用自建的lib库函数教程
    取出16进制位对应位数的数字是0还是1(C语言)
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13603914.html
Copyright © 2020-2023  润新知