码迷,mamicode.com
首页 > 其他好文 > 详细

topcoder srm 520 div1

时间:2018-01-20 14:02:35      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:cal   log   code   break   ali   efi   不同的   inter   last   

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

 

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

topcoder srm 520 div1

标签:cal   log   code   break   ali   efi   不同的   inter   last   

原文地址:https://www.cnblogs.com/jianglangcaijin/p/8320466.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!