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

    problem1 link

    设$f[i][j][k]$表示考虑了前$i$道题,剩下时间为$j$,剩下技能为$k$的最大得分.

    从小到大计算二元组$(j,k)$的话,在存储上可以省略掉$i$这一维.

    problem2 link

    首先,不同的提交状态有8种.预计算每一种提交状态的每一个分值的种数,设为$g[mask][score]$.对于$g[mask][score]$的计算,可以枚举$mask$包含的一个题目,设为$i$,其分值为$p_{i}$,那么第$i$道题得分如果为$x$,那么其他$mask^{'}=mask$^$2^{i}$题目得分为$score-x$,所以$g[mask][score]=sum_{x=1}^{p_{i}}g[mask^{'}][score-x]$

    最后从前向后考虑每个人的得分.设$f[i][score]$表示前$i$个人的得分降序排列且第$i$个人得分为$score$的方案数.设第$i+1$个人的得分为$y$,由于第$i$个人的得分一定大于$y$,所以$f[i+1][y]=sum_{x=y+1}^{MaxScore_{i}}f[i][x]$

    由于计算数组$g$和$f$都是连续求和,可以通过预处理前缀和或者后缀和来加速计算

    problem3 link

    将所有人按照是否攻击别人和是否被攻击成功分为四类,即YY,YN,NY,NN.设这四类的个数分别为$A,B,C,D,A+B+C+D=n$.所有的攻击一共有$T=A+B$个.

    明显如果$A+C>B+C$,那么答案为0.下面认为$C le B$

    现在就是要构造一个$T*2$的二维表,某一行的两列的两个值$r_{1},r_{2}$,表示有一条攻击是$r_{1}->r_{2}$

    对于第一类中的每个元素$e$,它一定在第一列第二列同时出现过,并且可能在第二列出现过多次.现在只考虑出现在第二列且被攻击成功的那一行,设其为$y$,设出现的第一列的行为$x$,那么有$x<y$.

    现在来计算把$A$个第一类元素放到这个表中的方案数.可以用动态规划来计算.设$f[T][A]$表示把$A$个元素放入到一个$T*2$表中的方案数.现在先假设所有的$A$个元素是一样的,即没有先后顺序.

    考虑第一行的第一列,有两种情况:

    (1)没有放置$A$中的元素,那么情况为$f[T-1][A]$

    (2)放置了一个,那么这个元素出现在第二列的行数在后面的$T-1$行中,且这$T-1$行的第二列中已经放置了$A-1$个,所以还有$(T-1)-(A-1)=T-A$个位置,即答案为$(T-A)*f[T-1][A-1]$

    所以$f[T][A]=f[T-1][A]+(T-A)*f[T-1][A-1]$

    现在对于第二列放置的每个第一类的元素,这一行所代表的攻击是成功的.也就是说对应的第一列也已经有了攻击者(可能是第一类或者第二类的元素).$f[T][A]$已经保证了对于第一类元素的合理性.

    现在现在第一列对应的$T-A=B$个元素(这些元素可能是第二类也可能是第一类但还没有攻击对手)还没有攻击的对象,因为这$B$个攻击中有$C$个需要是成功的,所以有$C_{B}^{C}$个选择.现在第一列还有$B-C$个还没有攻击对象,并且这些攻击都是失败的,所以只要不是它自己就行,所以每个有$n-1$种.

    最后所有的元素都是不同的,所以要乘以它们的阶乘.所以答案为$f[A+B][A]*C_{B}^{C}*(n-1)^{B-C}*A!*B!*C!$

    code for problem1

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    
    class SRMCodingPhase {
      public:
        int countScore(vector <int> points, vector <int> skills, int luck) {
          vector<vector<int>> f(76, vector<int>(luck + 1, -1));
          f[75][luck] = 0;
          const int b[] = {2, 4, 8};
          for (int i = 0; i < 3; ++ i) {
            const int point = points[i];
            const int skill = skills[i];
            for (int j = 0; j <= 75; ++ j) {
              for (int k = 0; k <= luck; ++ k) {
                if (f[j][k] == -1) {
                  continue;
                }
                for (int t = 0; t <= k && t < skill; ++ t) {
                  const int last_point = point - b[i] * (skill - t);
                  if (last_point <= 0) {
                    continue;
                  }
                  if (skill - t > j) {
                    continue;
                  }
                  f[j - (skill - t)][k - t] = max(f[j - (skill - t)][k - t], last_point + f[j][k]);
                }
              }
            }
          }
          int result = 0;
          for (int j = 0; j <= 75; ++ j) {
            for (int k = 0; k <= luck; ++ k) {
              result = max(result, f[j][k]);
            }
          }
          return result;
        }
    };
    

      

    code for problem2

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <string>
    using namespace std;
    
    #define mod 1000000007
    #define MAX_SCORE 200000
    
    int g[8][MAX_SCORE + 1];
    int f[20][MAX_SCORE + 1];
    
    class SRMIntermissionPhase {
      public:
        int countWays(vector<int> points, vector<string> description) {
          Initialize(points);
    
          const int mask0 = GetMask(description[0]);
          for (int i = 0; i <= MAX_SCORE; ++ i) {
            f[0][i] = GetRangeSum(mask0, i, i);
          }
          CalculateSuffixSum(0);
          const int person_number = (int)description.size();
          for (int i = 1; i < person_number; ++ i) {
            const int mask = GetMask(description[i]);
            for (int j = 0; j < MAX_SCORE; ++ j) {
              f[i][j] = (long long)GetRangeSum(mask, j, j) * f[i - 1][j + 1] % mod;
            }
            CalculateSuffixSum(i);
          }
          return f[person_number - 1][0];
        }
      private:
    
        void CalculateSuffixSum(int idx) {
          for (int i = MAX_SCORE - 1; i >= 0; -- i) {
            Add(f[idx][i], f[idx][i + 1]);
          }
        }
        void CalculatePrefixSum(int idx) {
          for (int i = 1; i <= MAX_SCORE; ++ i) {
            Add(g[idx][i], g[idx][i - 1]);
          }
        }
    
        int GetMask(const std::string& s) {
          int mask = 0;
          for (int i = 0; i < 3; ++ i) {
            if (s[i] == 'Y') {
              mask |= 1 << i;
            }
          }
          return mask;
        }
    
        void Initialize(const vector<int>& points) {
          g[0][0] = 1;
          CalculatePrefixSum(0);
          for (int i = 1; i < 8; ++ i) {
            int low_bit = 0;
            for (int j = 0; j < 3; ++ j) {
              if ((i & (1 << j)) != 0) {
                low_bit = j;
                break;
              }
            }
            const int other = i ^ (1 << low_bit);
            const int point = points[low_bit];
            for (int k = 1; k <= MAX_SCORE; ++ k) {
              g[i][k] = GetRangeSum(other, k - point, k - 1);
            }
            CalculatePrefixSum(i);
          }
        }
    
        int GetRangeSum(int mask, int left, int right) {
          if (left <= 0) {
            return g[mask][right];
          }
          int result = g[mask][right] - g[mask][left - 1];
          if (result < 0) {
            result += mod;
          }
          return result;
        }
        void Add(int &x, int y) {
          x += y;
          if (x >= mod) {
            x -= mod;
          }
        }
    };
    

    code for problem3

    #include <cstring>
    #include <iostream>
    #include <map>
    #include <sstream>
    #include <stdio.h>
    #include <string>
    #include <vector>
    using namespace std;
    
    #define mod 1000000007
    #define MAX_SIZE 2501
    
    int f[MAX_SIZE][MAX_SIZE];
    
    class SRMChallengePhase {
      public:
      int countWays(vector<string> codersAttempted, vector<string> codersChallenged)
      {
        const std::string s1 = Concat(codersAttempted);
        const std::string s2 = Concat(codersChallenged);
        const int n = (int)s1.size();
        int A = 0, B = 0, C = 0;
        for (int i = 0; i < n; ++i) {
          if (s1[i] == 'Y' && s2[i] == 'Y') {
            ++A;
          } else if (s1[i] == 'Y' && s2[i] == 'N') {
            ++B;
          } else if (s1[i] == 'N' && s2[i] == 'Y') {
            ++C;
          }
        }
        if (B < C) {
          return 0;
        }
        f[0][0] = 1;
        for (int i = 1; i <= A + B; ++i) {
          for (int j = 0; j <= A; ++j) {
            f[i][j] = f[i - 1][j];
            if (j > 0) {
              Add(f[i][j], (long long)(i - j) * f[i - 1][j - 1] % mod);
            }
          }
        }
        int result = f[A + B][A];
        for (int i = 1; i <= B - C; ++i) {
          result = (long long)result * (n - 1) % mod;
        }
        for (int i = 2; i <= A; ++i) {
          result = (long long)result * i % mod;
        }
        for (int i = B; i >= 2; --i) {
          result = (long long)result * i % mod;
          if (i >= B - C + 1) {
            result = (long long)result * i % mod;
          }
        }
        return result;
      }
    
      private:
      void Add(int& x, int y)
      {
        if (y < 0) {
          y += mod;
        }
        x += y;
        if (x >= mod) {
          x -= mod;
        }
      }
      std::string Concat(const vector<string>& str)
      {
        std::string s = "";
        for (auto x : str) {
          s += x;
        }
        return s;
      }
    };
    

      

  • 相关阅读:
    svn 指定不更新目录
    C# 修改win环境变量 来加载dll库
    基本组件
    在SD卡上创建/删除文件夹 使用DDMS透视图管理SD卡
    linux中图形界面改成文本
    表格布局和线性布局
    文件操作
    静态库的生成和调用
    船载电子海图系统(E C S )概述
    GPS全球定位系统构成及原理
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/8320466.html
Copyright © 2011-2022 走看看