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

    problem1 link

    首先由$P$中任意两元素的绝对值得到集合$Q$。然后枚举$Q$中的每个元素作为集合$D$中的最大值$Max$,这样就能确定最后集合$D$中的最小值要大于等于$Min=frac{Max+k-1}{k}$。然后再枚举$S$中元素的最小值即可依次从小到大确定$S$中的所有值。因为假设$S$中最小的元素是$x$,且当前最大元素是$y$,那么对于一个元素$z,z>y$,要么不选它;如果要选进来就要满足$z-xleq Max$且$z-ygeq Min$。这样可以用一个简单的dp来解决。

    problem2 link

    设$s_{i}$表示连续$i$个元素任意两个相邻元素$x,y$满足$x>y$且$x$%$y$=0的方案数。$s$数组可以通过简单的dp来计算得到。

    $f_{x}$表示长度为$x$的数组$A$的方案数。答案为$f_{n}$。$f_{0}=1$,$f_{t}=sum_{r=1}^{t}f_{t-r}s_{r}(-1)^{r+1}=f_{t-1}s_{1}-f_{t-2}s_{2}+f_{t-3}s_{3}...$.其中$s_{1}=k$。

    这个容斥可以这样理解:首先不理会$A_{n-1}$和$A_{n}$的关系,那么$A_{n}$有$s_{1}=k$种选择,所以$f_{n}=f_{n-1}s_{1}$。这样会导致$f_{n-1},f_{n}$不满足第二个条件,那么$f_{n-2}s_{2}$包含了所有的这种情况,同时$f_{n-2}s_{2}$还包含了$f_{n-2}$和$f_{n-1}$不满足第二个条件的情况,所以减去$f_{n-2}s_{2}$然后继续向后计算。

    由于$k$最多只有$50000$,那么最多只会出现连续 16个数字是倍数关系,也就是说当$r>16$时$s_{r}=0$。所以$f_{t}=sum_{r=1}^{min(t,16)}f_{t-r}s_{r}(-1)^{r+1}$

    problem3 link

    枚举排列的第一个数字。所有的情况都要乘上$m!$,所以把它最后再乘。

    当$n=2$时,设为$a_{1},a_{2}$,那么答案为$frac{1}{a_{1}+a_{2}}=a_{2}^{-1}left (frac{1}{a_{1}+a_{2}}  ight )$

    当$n=3$时,设为$a_{1},a_{2},a_{3}$,那么第一个固定时答案为

    $frac{1}{(a_{1}+a_{2})(a_{1}+a_{2}+a_{3})}+frac{1}{(a_{1}+a_{3})(a_{1}+a_{3}+a_{2})}$

    $=a_{3}^{-1}left ( (a_{1}+a_{2})^{-1}-(a_{1}+a_{2}+a_{3})^{-1} ight )+a_{2}^{-1}left ( (a_{1}+a_{3})^{-1}-(a_{1}+a_{3}+a_{2})^{-1} ight )$

    $=(a_{2}a_{3})^{-1}left ( frac{a_{2}}{a_{1}+a_{2}}+frac{a_{3}}{a_{1}+a_{3}}-frac{a_{2}+a_{3}}{a_{1}+a_{2}+a_{3}} ight )$

    当$n=4$时,前两项为$a_{1},a_{2}$时,后两项有两种组合,和为$(a_{3}a_{4})^{-1}left ( frac{a_{3}}{a_{1}+a_{2}+a_{3}}+frac{a_{4}}{a_{1}+a_{2}+a_{4}}-frac{a_{3}+a_{4}}{a_{1}+a_{2}+a_{3}+a_{4}} ight )$,这相当于$a_{1}+a_{2}$是$n=3$时的$a_{1}$。

    所以对答案的贡献为$frac{1}{a_{1}+a_{2}}(a_{3}a_{4})^{-1}left ( frac{a_{3}}{a_{1}+a_{2}+a_{3}}+frac{a_{4}}{a_{1}+a_{2}+a_{4}}-frac{a_{3}+a_{4}}{a_{1}+a_{2}+a_{3}+a_{4}} ight )$

    $=(a_{3}a_{4})^{-1}left ( frac{1}{a_{1}+a_{2}}-frac{1}{a_{1}+a_{2}+a_{3}}+frac{1}{a_{1}+a_{2}}-frac{a_{1}}{a_{1}+a_{2}+a_{4}}-(frac{1}{a_{1}+a_{2}}-frac{1}{a_{1}+a_{2}+a_{3}+a_{4}}) ight )$

    $=(a_{3}a_{4})^{-1}left ( frac{1}{a_{1}+a_{2}}-frac{1}{a_{1}+a_{2}+a_{3}}-frac{1}{a_{1}+a_{2}+a_{4}}+frac{1}{a_{1}+a_{2}+a_{3}+a_{4}} ight )$

    $=(a_{2}a_{3}a_{4})^{-1}left ( frac{a_{2}}{a_{1}+a_{2}}-frac{a_{2}}{a_{1}+a_{2}+a_{3}}-frac{a_{2}}{a_{1}+a_{2}+a_{4}}+frac{a_{2}}{a_{1}+a_{2}+a_{3}+a_{4}} ight )$

    所以加上前两项是$a_{1},a_{3}$以及$a_{1},a_{4}$,总的答案为

    $(a_{2}a_{3}a_{4})^{-1}left ( frac{a_{2}}{a_{1}+a_{2}}+frac{a_{3}}{a_{1}+a_{3}}+frac{a_{4}}{a_{1}+a_{4}}-frac{a_{2}+a_{3}}{a_{1}+a_{2}+a_{3}}-frac{a_{2}+a_{4}}{a_{1}+a_{2}+a_{4}}-frac{a_{3}+a_{4}}{a_{1}+a_{3}+a_{4}}+frac{a_{2}+a_{3}+a_{4}}{a_{1}+a_{2}+a_{3}+a_{4}} ight )$

    所以对于$n$项来说,第一项为$a_{1}$的答案为$sum_{pin P}(-1)^{1+|p|}frac{sum_{xin p}x}{a_{1}+sum_{xin p}x}$。其中$P$表示$a_{2},a_{3},..,a_{n}$的任意非空子集的集合。理论上有$2^{n-1}-1$个。但是由于所有的数字之和最多为1000,所以可以直接统计和为$y$的有多少种。

    code for problem1

    #include <algorithm>
    #include <vector>
    
    class CliqueParty {
     public:
      int maxsize(std::vector<int> A, int k) {
        int n = static_cast<int>(A.size());
        std::sort(A.begin(), A.end());
        std::vector<int> a;
        for (int i = 0; i < n; ++i) {
          for (int j = i + 1; j < n; ++j) {
            a.push_back(A[j] - A[i]);
          }
        }
        std::sort(a.begin(), a.end());
        auto Cal = [&](const int Max) {
          const int Min = (Max + k - 1) / k;
          int ans = 0;
          for (int k = 0; k < n; ++k) {
            std::vector<std::vector<int>> f(n, std::vector<int>(n, -1));
            f[k][k] = 1;
            for (int i = k + 1; i < n; ++i) {
              for (int j = k; j <= i - 1; ++j) {
                f[i][j] = f[i - 1][j];
                if (f[i - 1][j] != -1 && A[i] - A[j] >= Min && A[i] - A[k] <= Max) {
                  f[i][i] = std::max(f[i][i], f[i - 1][j] + 1);
                }
              }
            }
            for (int i = k; i < n; ++i) {
              ans = std::max(ans, f[n - 1][i]);
            }
          }
          return ans;
        };
        int result = 0;
        for (size_t i = 0; i < a.size(); ++i) {
          if (i == 0 || a[i] != a[i - 1]) {
            result = std::max(result, Cal(a[i]));
          }
        }
        return result;
      }
    };

    code for problem2

    #include <vector>
    
    class DivFree {
     public:
      int dfcount(int n, int k) {
        constexpr int kMaxT = 16;
        constexpr int kMod = 1000000007;
        std::vector<std::vector<int>> f(kMaxT + 1, std::vector<int>(k + 1));
        std::vector<int> s(kMaxT + 1);
        for (int i = 1; i <= k; ++i) {
          f[1][i] = 1;
        }
        s[1] = k;
        auto Add = [&](int &x, int y) {
          x += y;
          if (x >= kMod) {
            x -= kMod;
          }
        };
        for (int i = 2; i <= kMaxT; ++i) {
          for (int j = 1; j <= k; ++j) {
            for (int t = j + j; t <= k; t += j) {
              Add(f[i][t], f[i - 1][j]);
            }
          }
          for (int j = 1; j <= k; ++j) {
            Add(s[i], f[i][j]);
          }
        }
        std::vector<int> dp(n + 1);
        dp[0] = 1;
        for (int i = 1; i <= n; ++i) {
          for (int j = 1; j <= kMaxT && j <= i; ++j) {
            int k = static_cast<int>(1ll * dp[i - j] * s[j] % kMod);
            if (j % 2 == 1) {
              Add(dp[i], k);
            } else {
              Add(dp[i], kMod - k);
            }
          }
        }
        return dp[n];
      }
    };

    code for problem3

    #include <algorithm>
    #include <vector>
    
    class Permutant {
     public:
      int counthis(const std::vector<int> &a) {
        constexpr int kMod = 1000000007;
        int n = static_cast<int>(a.size());
        int s = std::accumulate(a.begin(), a.end(), 0);
        std::vector<long long> inv(s + 1);
        inv[1] = 1;
        for (int i = 2; i <= s; ++i) {
          inv[i] = (kMod - kMod / i) * inv[kMod % i] % kMod;
        }
        auto Add = [&](int &x, long long y) {
          x += static_cast<int>(y % kMod);
          if (x >= kMod) {
            x -= kMod;
          }
        };
        int result = 0;
        for (int t = 0; t < n; ++t) {
          std::vector<std::vector<std::vector<int>>> dp(
              n + 1, std::vector<std::vector<int>>(2, std::vector<int>(s + 1)));
          dp[0][0][0] = 1;
          for (int i = 0; i < n; ++i) {
            for (int j = 0; j < 2; ++j) {
              for (int k = 0; k <= s; ++k) {
                Add(dp[i + 1][j ^ 1][k + a[i]], dp[i][j][k]);
                if (i != t) {
                  Add(dp[i + 1][j][k], dp[i][j][k]);
                }
              }
            }
          }
          int num = 0;
          for (int i = 0; i < 2; ++i) {
            for (int j = 0; j <= s; ++j) {
              long long x = inv[j] * (j - a[t]) % kMod;
              if (i == 0) {
                Add(num, x * dp[n][i][j] % kMod);
              } else {
                Add(num, (kMod - x) * dp[n][i][j] % kMod);
              }
            }
          }
          for (int i = 0; i < n; ++i) {
            if (i != t) {
              num = static_cast<int>(inv[a[i]] * num % kMod);
            }
          }
          Add(result, num);
        }
        if (n == 1) {
          result = 1;
        }
        for (int i = 1; i <= s; ++i) {
          result = static_cast<int>(1ll * result * i % kMod);
        }
        return result;
      }
    };
  • 相关阅读:
    作业29——制作首页的显示列表。
    作业28——发布功能完成。
    作业27——登录之后更新导航
    作业26——完成登录功能,用session记住用户名
    作业25——完成注册功能
    作业24——通过用户模型,对数据库进行增删改查操作。
    作业23——连接mysql数据库,创建用户模型
    作业22——管理信息系统的开发与管理
    作业——21加载静态文件,父模板的继承和扩展
    值类型与引用类型区别
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6955323.html
Copyright © 2011-2022 走看看