zoukankan      html  css  js  c++  java
  • topcoder srm 686 div1

    problem1 link

    左括号和右括号较少的一种不会大于20。假设左括号少。设$f[i][mask][k]$表示处理了前$i$个字符,其中留下的字符以$k$开头($k=0$表示'(',$k=1$表示'['),且所有留下的字符状态为$mask$,($mask$的最高位为1,其他位为0表示另一种括号,否则表示跟最高位相同的符号)。

    problem2 link

    给定$n,m$,$n$个数字的排列有$n!$种,设其中某一种为$P_{i}$,设$P_{i}$中循环的个数$f(P_{i})=t_{i}$,那么$P_{i}$对答案的贡献为$t_{i}^{m}$。设所有排列的集合为$S$,计算$sum_{P_{i}in S}f(P_{i})^{m}$。$1leq nleq 100000,0leq mleq 300$

    给出一些定义:

    (1)第一类斯特灵数:$s(n,k)$,表示将$n$个元素排列成$k$个轮换的个数,递推公式:$s(n,k)=(n-1)s(n-1,k)+s(n-1,k-1),n>0$

    (2)第二类斯特灵数:$S(n,k)$,表示将$n$个元素分成$k$个非空集合的方案数,递推公式:$S(n,k)=k*S(n-1,k)+S(n-1,k-1),n>0$

    (3)$x^{n}=sum_{k=0}^{n}S(n,k)x(x-1)...(x-k+1),ngeq 0$.这个可以用数学归纳法证明。

    (4)$x(x+1)...(x+n-1)=sum_{k=0}^{n}s(n,k)x^{k},ngeq 0$.这个可以用数学归纳法证明。

    ==========分隔符=========

    现在回到题目。需要求的是$ans=sum_{k=0}^{n}s(n,k)k^{m}$,借助上面第(3)个公式得到:

    $ans=sum_{k=0}^{n}s(n,k)k^{m}$

    $=sum_{k=0}^{n}s(n,k)sum_{t=0}^{m}S(m,t)k(k-1)...(k-t+1)$

    $=sum_{t=0}^{m}S(m,t)sum_{k=0}^{n}s(n,k)k(k-1)...(k-t+1)$

    现在考虑 $sum_{k=0}^{n}s(n,k)k(k-1)...(k-t+1)$

    对公式(4)两端求$t$阶导数得到:$(x(x+1)...(x+n-1))^{(t)}=sum_{k=0}^{n}s(n,k)k(k-1)...(k-t+1)x^{k-t}$.

    如果令$x=1$就得到了$sum_{k=0}^{n}s(n,k)k(k-1)...(k-t+1)$。

    现在就是需要计算$(x(x+1)...(x+n-1))^{(t)}_{x=1}$的值。

    令$u=x-1$,那么就是求$((u+1)(u+2)...(u+n))^{(t)}_{u=0}$的值。

    $(u+1)(u+2)...(u+n)=a_{n,0}+a_{n,1}u+...+a_{n,t}u^{t}+...+a_{n,n}u^{n}$

    现在只需要计算出$a_{n,t}$即可,那么$sum_{k=0}^{n}s(n,k)k(k-1)...(k-t+1)=a_{n,t}*t!$

     下面用数学归纳法证明:$a_{n,t}=s(n+1,t+1)$.

    (1)假设$t$固定,小于等于$n-1$时均成立;即$a_{n-1,t}=s(n,t+1)$.

    (2)对于$(u+1)(u+2)...(u+n)中$中$u_{t}$的系数的所有项是由$n$项中选出$n-t$项的乘积组成的。那么如果某一项乘积包含$n$时,就是$n*a_{n-1,t}=n*s(n,t+1)$;如果不包含$n$,那么就是由$[1,n-1]$中任意选出$n-t$项,这其实就是$a_{n-1,t-1}=s(n,t)$。

    所以$(u+1)(u+2)...(u+n-1)$中$u_{t}$的系数$a_{n,t}=n*s(n,t+1)+s(n,t)=s(n+1,t+1)$.

    problem3 link

    一顿乱搜。

    code for problem1

    #include <algorithm>
    #include <cstring>
    #include <string>
    
    constexpr int kMAXN = 20;
    
    long long f[2][1 << kMAXN][2];
    
    class BracketSequenceDiv1 {
     public:
      long long count(std::string s) {
        int n = static_cast<int>(s.size());
        int num = 0;
        for (int i = 0; i < n; ++i) {
          if (s[i] == '(' || s[i] == '[') {
            ++num;
          }
        }
        if (num > n - num) {
          std::reverse(s.begin(), s.end());
          for (int i = 0; i < n; ++i) {
            if (s[i] == '(') {
              s[i] = ')';
            } else if (s[i] == ')') {
              s[i] = '(';
            } else if (s[i] == '[') {
              s[i] = ']';
            } else {
              s[i] = '[';
            }
          }
          num = n - num;
        }
    
        int pre = 0, cur = 1;
        memset(f[pre], 0, sizeof(f[pre]));
        f[0][0][0] = 1;
        for (int i = 1; i <= n; ++i) {
          char c = s[i - 1];
          memset(f[cur], 0, sizeof(f[cur]));
          for (int j = 0; j < (1 << num); ++j) {
            for (int k = 0; k < 2; ++k) {
              long long p = f[pre][j][k];
              if (p == 0) {
                continue;
              }
              f[cur][j][k] += p;
              if (c == '(') {
                if (j == 0) {
                  f[cur][1][0] += p;
                } else {
                  f[cur][j << 1 | (k ^ 1)][k] += p;
                }
              } else if (c == '[') {
                if (j == 0) {
                  f[cur][1][1] += p;
                } else {
                  f[cur][j << 1 | k][k] += p;
                }
              } else if (c == ')') {
                if (j != 0 && (k ^ (j & 1)) != 0) {
                  f[cur][j >> 1][k] += p;
                }
              } else {
                if (j != 0 && (0 == (k ^ (j & 1)))) {
                  f[cur][j >> 1][k] += p;
                }
              }
            }
          }
          pre ^= 1;
          cur ^= 1;
        }
        return f[pre][0][0] + f[pre][0][1] - 1;
      }
    };

    code for problem2

    #include <vector>
    
    constexpr int N = 101000;
    constexpr int kMod = 1000000007;
    
    int g[N][305];
    
    int p[N];
    
    int S[305][305];
    
    class CyclesNumber {
     public:
      std::vector<int> getExpectation(const std::vector<int> &n,
                                      const std::vector<int> &m) {
        p[0] = 1;
        for (int i = 1; i < N; ++i)
          p[i] = static_cast<int>(1ll * p[i - 1] * i % kMod);
    
        S[0][0] = 1;
        S[1][1] = 1;
        S[2][1] = S[2][2] = 1;
        for (int i = 3; i <= 300; ++i) {
          for (int k = 1; k <= i; ++k) {
            S[i][k] =
                static_cast<int>((1ll * k * S[i - 1][k] + S[i - 1][k - 1]) % kMod);
          }
        }
    
        g[0][0] = 1;
        g[1][1] = 1;
        g[2][1] = g[2][2] = 1;
        for (int i = 3; i < N; ++i) {
          for (int j = 1; j <= 301; ++j) {
            g[i][j] = static_cast<int>(
                (1ll * (i - 1) * g[i - 1][j] + g[i - 1][j - 1]) % kMod);
          }
        }
    
        int num = static_cast<int>(n.size());
    
        std::vector<int> result(num);
        for (int i = 0; i < num; ++i) {
          result[i] = Cal(n[i], m[i]);
        }
        return result;
      }
    
     private:
      void Add(int &x, int y) {
        x += y;
        if (x >= kMod) {
          x -= kMod;
        }
      }
    
      int Cal(int n, int m) {
        if (m == 0) {
          return p[n];
        }
        if (n == 1) {
          return 1;
        }
    
        int ans = 0;
        for (int t = 1; t <= m; ++t) {
          Add(ans, static_cast<int>(1ll * S[m][t] * p[t] % kMod * g[n + 1][t + 1] %
                                    kMod));
        }
        return ans;
      }
    };

    code for problem3

    #include <algorithm>
    #include <vector>
    
    class XorPuzzle {
     public:
      std::vector<int> find(int k, const std::vector<int> a) {
        int n = static_cast<int>(a.size());
        int m = 1 << k;
        if (n == m) {
          int s = 0;
          for (int x : a) {
            s ^= x;
          }
          if (s != 0) {
            return {-1};
          }
        }
        std::vector<int> b(m);
        std::vector<int> c(m);
        for (int i = 0; i < m; ++i) {
          b[i] = c[i] = i;
        }
        for (int i = 0; i < n; ++i) {
          if (a[i] == (b[i] ^ c[i])) {
            continue;
          }
          int j = i;
          while (j <= i) {
            if (j == i) {
              std::random_shuffle(b.begin() + j, b.end());
            }
            int p = 0;
            while (c[p] != (a[j] ^ b[j])) {
              ++p;
            }
            std::swap(c[p], c[j]);
            if (p >= i) {
              break;
            } else {
              int t = 0;
              while (b[t] != (a[p] ^ c[p])) {
                ++t;
              }
              std::swap(b[t], b[p]);
              j = t;
            }
          }
        }
        std::vector<int> result(n * 2);
        std::copy(b.begin(), b.begin() + n, result.begin());
        std::copy(c.begin(), c.begin() + n, result.begin() + n);
        return result;
      }
    };
  • 相关阅读:
    Java获取输入
    [转载]Eclipse快捷键 10个最有用的快捷键
    运算符优先级
    Error:Cannot build artifact 'seckill:war' because it is included into a circular dependency (artifact 'seckill:war', artifact 'seckill:war exploded')
    spring boot 扫描不到controller情形一
    注解控制事物方法
    <转载>标签接口
    生成二维码(QRcode(for java version)生成二维码)
    Linux 常见命令
    【C#】File.WriteAllText 类的使用(实现自定义日志记录)
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6915067.html
Copyright © 2011-2022 走看看