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;
}
};

  

topcoder srm 520 div1的更多相关文章

  1. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

  2. Topcoder Srm 726 Div1 Hard

    Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...

  3. topcoder srm 714 div1

    problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...

  4. topcoder srm 738 div1 FindThePerfectTriangle(枚举)

    Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle wi ...

  5. Topcoder SRM 602 div1题解

    打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...

  6. Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

    Problem Statement      The Happy Letter game is played as follows: At the beginning, several players ...

  7. Topcoder SRM 584 DIV1 600

    思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...

  8. TopCoder SRM 605 DIV1

    604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...

  9. topcoder srm 575 div1

    problem1 link 如果$k$是先手必胜那么$f(k)=1$否则$f(k)=0$ 通过对前面小的数字的计算可以发现:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其 ...

随机推荐

  1. MyBatis基础入门《七》查询参数传入对象

    MyBatis基础入门<七>查询参数传入对象 描述: 在执行查询语句的时候,传入的参数是一个对象,依据对象的属性,进行检索数据.此时,书写SQL语句中的条件时,其参数需要和对象中的属性保持 ...

  2. JavaScript-switch-case-电话系统

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  3. linux 中的screen出现cannot find terminfo entry 的错误

    事情的起因: 本地使用urxvt terminal ,使用ssh方式远程登录服务器,远程在服务器端执行screen命令,然后就出现了cannot find terminfo entry的错误. 解决方 ...

  4. 强化学习--Policy Gradient

    Policy Gradient综述: Policy Gradient,通过学习当前环境,直接给出要输出的动作的概率值.   Policy Gradient  不是单步更新,只能等玩完一个epoch,再 ...

  5. Lua逻辑操作符

    [1]逻辑操作符and.or和not 应用示例: ) ) -- nil ) -- false ) ) ) ) ) ) ) print(not nil) -- ture print(not false) ...

  6. OpenCV LK光流法测试

    OpenCV版本: 3.2.0 例程文件目录/samples/cpp/lkdemo.cpp 原始程序是采集相机数据,台式机没有摄像头,用Euroc测试集,偷ORB_SLAM2 /Examples/Mo ...

  7. c++学习笔记(七)- lambda表达式 迭代器 算法

    关于lambda表达式: 刷题的时候遇到一句代码不懂: char ch = *it;auto it2 = find_if(it, b.end(), [ch](char x){ return x != ...

  8. Axure RP Extension for Chrome修复

    Axure RP Extension for Chrome安装之前一直用 Firefox 浏览器浏览原型文件,一直用不惯,而且用 Firefox 的唯一目的就是看原型.其他都是用 Chrome 浏览器 ...

  9. amoeba读写分离

    第一单元   高性能mysql读写分离的实现 5.1      mysql读写分离 5.1.1  mysql读写分离概述 5.1.2  mysql读写分离原理 5.2      mysql读写分离配置 ...

  10. 基于Redis实现分布式锁实战

    背景在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成等等.大部分的解决方案是基于DB实现的,Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端 ...