• topcoder srm 625 div1


    problem1 link

    假设第$i$种出现的次数为$n_{i}$,总个数为$m$,那么排列数为$T=frac{m!}{prod_{i=1}^{26}(n_{i}!)}$

    然后计算回文的个数,只需要考虑前一半,得到个数为$R$,那么答案为$frac{R}{T}$.

    为了防止数字太大导致越界,可以分解为质因子的表示方法。

    problem2 link

    假设终点所在的位置为$(tx,ty)$,那么所有底面是$1x1$的格子$(x,y)$一定满足$(x-tx)mod(3)=0,(y-ty)mod(3)=0$

    把每个这样的点拆成两个点然后建立最小割的图。

    源点与所有的$b$相连,终点与汇点相连,流量为无穷,割边不会在这里产生。

    如果不是洞,那么这个格子拆成的两个点流量为1,表示将这个格子设为洞。

    每个格子向周围连边,流量为将中间的两个格子设为洞的代价。

    最后最小割就是答案。

    problem3 link

    首先考虑集合之间的关系。设$f[i][j]$表示前$i$个人分成$j$个集合的方案数。初始化$f[1][1]=n$。那么有:

    (1)$f[i+1][j+1]=f[i][j]*j$表示新加一个集合,可以在任意两个集合之间

    (2)$f[i+1][j]=f[i][j]*j*2$表示新加的元素与之前的某一个集合在一起,可以放在那个集合的前后,所以有$j*2$种方法

    (3)$f[i+1][j-1]=f[i][j]*j$表示合并两个集合,可以在任意两个集合之间插入从而进行合并

    最后就是对于$f[x][y]$来说,有多少种方式可以在$n$个位置上放置$x$个使得有$y$个集合并且任意两个集合不相邻。令$m=n-(x-y)$,那么相当于在$m$个位置中放置$y$个,使得任意两个不相邻。由于$f[1][1]=n$那么这$y$个集合的排列已经计算了,所以现在可以假设这$y$个元素的第一个放在$m$个位置的第一个位置,那么第二个位置也不能放置了。所以还剩$m-2$个位置,$y-1$个元素。由于每放置一个元素其后面的位置就不能放置了,所以可以把剩下$y-1$个元素的位置与其后面相邻的位置绑定成一个位置,这样的话,就是$m-2-(y-1)$个位置,$y-1$个元素,即$C_{m-2-(y-1)}^{y-1}=C_{n-(x-y)-2-(y-1)}^{y-1}=C_{n-x-1}^{y-1}$

    code for problem1

    #include <cmath>
    #include <string>
    #include <vector>
    
    class PalindromePermutations {
     public:
      double palindromeProbability(const std::string &word) {
        std::vector<int> h(26, 0);
        for (auto e : word) {
          ++h[e - 'a'];
        }
        int old_idx = -1;
        for (int i = 0; i < 26; ++i) {
          if (h[i] % 2 == 1) {
            if (old_idx != -1) {
              return 0.0;
            }
            old_idx = i;
          }
        }
        auto total = Compute(h);
        if (old_idx != -1) {
          --h[old_idx];
        }
        for (auto &e : h) {
          e /= 2;
        }
        auto target = Compute(h);
        double result = 1.0;
        for (int i = 2; i < 50; ++i) {
          result *= std::pow(i, target[i] - total[i]);
        }
        return result;
      }
    
     private:
      std::vector<int> Compute(const std::vector<int> &h) {
        std::vector<int> result(50, 0);
        auto Add = [&](int x, int sgn) {
          for (int i = 2; i <= x; ++i) {
            int k = i;
            for (int j = 2; j * j <= k; ++j) {
              while (k % j == 0) {
                result[j] += sgn;
                k /= j;
              }
            }
            if (k != 1) {
              result[k] += sgn;
            }
          }
        };
        int n = 0;
        for (auto e : h) {
          Add(e, -1);
          n += e;
        }
        Add(n, 1);
        return result;
      }
    };

    code for problem2

    #include <limits>
    #include <unordered_map>
    #include <vector>
    
    template <typename FlowType>
    class MaxFlowSolver {
      static constexpr FlowType kMaxFlow = std::numeric_limits<FlowType>::max();
      static constexpr FlowType kZeroFlow = static_cast<FlowType>(0);
      struct node {
        int v;
        int next;
        FlowType cap;
      };
    
     public:
      int VertexNumber() const { return used_index_; }
    
      FlowType MaxFlow(int source, int sink) {
        source = GetIndex(source);
        sink = GetIndex(sink);
    
        int n = VertexNumber();
        std::vector<int> pre(n);
        std::vector<int> cur(n);
        std::vector<int> num(n);
        std::vector<int> h(n);
        for (int i = 0; i < n; ++i) {
          cur[i] = head_[i];
          num[i] = 0;
          h[i] = 0;
        }
        int u = source;
        FlowType result = 0;
        while (h[u] < n) {
          if (u == sink) {
            FlowType min_cap = kMaxFlow;
            int v = -1;
            for (int i = source; i != sink; i = edges_[cur[i]].v) {
              int k = cur[i];
              if (edges_[k].cap < min_cap) {
                min_cap = edges_[k].cap;
                v = i;
              }
            }
            result += min_cap;
            u = v;
            for (int i = source; i != sink; i = edges_[cur[i]].v) {
              int k = cur[i];
              edges_[k].cap -= min_cap;
              edges_[k ^ 1].cap += min_cap;
            }
          }
          int index = -1;
          for (int i = cur[u]; i != -1; i = edges_[i].next) {
            if (edges_[i].cap > 0 && h[u] == h[edges_[i].v] + 1) {
              index = i;
              break;
            }
          }
          if (index != -1) {
            cur[u] = index;
            pre[edges_[index].v] = u;
            u = edges_[index].v;
          } else {
            if (--num[h[u]] == 0) {
              break;
            }
            int k = n;
            cur[u] = head_[u];
            for (int i = head_[u]; i != -1; i = edges_[i].next) {
              if (edges_[i].cap > 0 && h[edges_[i].v] < k) {
                k = h[edges_[i].v];
              }
            }
            if (k + 1 < n) {
              num[k + 1] += 1;
            }
            h[u] = k + 1;
            if (u != source) {
              u = pre[u];
            }
          }
        }
        return result;
      }
    
      MaxFlowSolver() = default;
    
      void Clear() {
        edges_.clear();
        head_.clear();
        vertex_indexer_.clear();
        used_index_ = 0;
      }
    
      void InsertEdge(int from, int to, FlowType cap) {
        from = GetIndex(from);
        to = GetIndex(to);
        AddEdge(from, to, cap);
        AddEdge(to, from, kZeroFlow);
      }
    
     private:
      int GetIndex(int idx) {
        auto iter = vertex_indexer_.find(idx);
        if (iter != vertex_indexer_.end()) {
          return iter->second;
        }
        int map_idx = used_index_++;
        head_.push_back(-1);
        return vertex_indexer_[idx] = map_idx;
      }
    
      void AddEdge(int from, int to, FlowType cap) {
        node p;
        p.v = to;
        p.cap = cap;
        p.next = head_[from];
        head_[from] = static_cast<int>(edges_.size());
        edges_.emplace_back(p);
      }
    
      std::vector<node> edges_;
      std::vector<int> head_;
    
      std::unordered_map<int, int> vertex_indexer_;
      int used_index_ = 0;
    };
    
    class BlockTheBlockPuzzle {
      static constexpr int kInfinite = 1000000;
    
     public:
      int minimumHoles(const std::vector<std::string> &S) {
        MaxFlowSolver<int> solver;
        int n = static_cast<int>(S.size());
        int source = -1;
        int sink = -2;
        int tx = -1, ty = -1;
        for (int i = 0; i < n; ++i) {
          for (int j = 0; j < n; ++j) {
            if (S[i][j] == '$') {
              tx = i;
              ty = j;
            }
          }
        }
    
        auto P0 = [&](int i, int j) { return i * n + j; };
        auto P1 = [&](int i, int j) { return i * n + j + n * n; };
    
        for (int i = 0; i < n; ++i) {
          for (int j = 0; j < n; ++j) {
            if (i % 3 == tx % 3 && j % 3 == ty % 3) {
              if (S[i][j] == '$') {
                solver.InsertEdge(P1(i, j), sink, kInfinite);
              }
              if (S[i][j] == 'b') {
                solver.InsertEdge(source, P0(i, j), kInfinite);
              }
              if (S[i][j] != 'H') {
                solver.InsertEdge(P0(i, j), P1(i, j),
                                  S[i][j] == '.' ? 1 : kInfinite);
              }
              if (i + 3 < n) {
                auto cost = GetCost(S, i + 1, j, i + 2, j);
                solver.InsertEdge(P1(i, j), P0(i + 3, j), cost);
                solver.InsertEdge(P1(i + 3, j), P0(i, j), cost);
              }
              if (j + 3 < n) {
                auto cost = GetCost(S, i, j + 1, i, j + 2);
                solver.InsertEdge(P1(i, j), P0(i, j + 3), cost);
                solver.InsertEdge(P1(i, j + 3), P0(i, j), cost);
              }
            }
          }
        }
        auto result = solver.MaxFlow(source, sink);
        if (result >= kInfinite) {
          return -1;
        }
        return result;
      }
    
     private:
      int GetCost(const std::vector<std::string> &s, int x1, int y1, int x2,
                  int y2) {
        if (s[x1][y1] == 'b' || s[x2][y2] == 'b') {
          return kInfinite;
        }
        int ans = 0;
        if (s[x1][y1] == '.') {
          ++ans;
        }
        if (s[x2][y2] == '.') {
          ++ans;
        }
        return ans;
      }
    };

    code for problem3

    constexpr int kMod = 1000000007;
    constexpr int kMax = 2000;
    
    int f[kMax + 1][kMax + 1];
    int C[kMax + 1][kMax + 1];
    
    class Seatfriends {
     public:
      int countseatnumb(int N, int K, int G) {
        f[1][1] = N;
        for (int i = 1; i < K; ++i) {
          for (int j = 1; j <= G; ++j) {
            long long p = f[i][j];
            if (p == 0) {
              continue;
            }
            if (j < G) {
              (f[i + 1][j + 1] += static_cast<int>(p * j % kMod)) %= kMod;
            }
            (f[i + 1][j - 1] += static_cast<int>(p * j % kMod)) %= kMod;
            (f[i + 1][j] += static_cast<int>(p * 2 * j % kMod)) %= kMod;
          }
        }
        if (K == N) {
          return f[K][0];
        }
    
        C[0][0] = 1;
        for (int i = 1; i <= N; ++i) {
          C[i][0] = C[i][i] = 1;
          for (int j = 1; j < i; ++j)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % kMod;
        }
    
        long long ans = 0;
        for (int j = 1; j <= G; ++j) {
          ans += static_cast<long long>(f[K][j]) * C[N - K - 1][j - 1] % kMod;
        }
        return static_cast<int>(ans % kMod);
      }
    };
  • 相关阅读:
    svg
    vuex的模块
    es6的新增方法和es5数组的一些方法
    vue的响应规则
    简单的解构赋值
    vuex的四种状态
    indexDB
    token验证
    C# 委托与事件的DEMO
    WPF MVVM 键盘按键事件绑定
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/9901977.html
Copyright © 2020-2023  润新知