topcoder srm 585 div1
problem1 link
最优的策略就是从最低下一层开始,每两层的三个节点的子树都可以用一次遍历覆盖。
problem2 link
从大到小依次放置每一种数字,并记录已经放置的数字一共有多少个$m$以及有多少个严格的升序列$K$。那个如果新放置的一个数字(必然小于序列中所有的数字)放在了升序列的开头,那么升序列个数不变;否则升序列的个数增加1.所以有$K$个位置可以使得升序列个数不变,而有$n+1-K$个位置使得升序列个数增加1.现在考虑新放置的数字有多个的情况。假设新放置的数字有$n$个,首先将他们插入到原来的序列前现将其分为$t$组,要求每一组插入的时候是连续的。那么每一组中前面的数字必定是有几个就会使得升序列个数增加几个,即一定至少增加$n-t$.那么如果$t$组中选择$x$组放在之前增序列的开头,剩下的$t-x$组放在其他位置,那么增加的增序列的总个数为$(n-t)+(t-x)$,方案数为$C_{K}^{x}C_{m+1-K}^{t-x}$.
problem3 link
首先将边上的$4m$个点按照顺时针看作一个序列,那么对于序列中的每个点$i$可以计算一个$left[i],right[i]$。$left[i]$表示在$i$前面最远的点满足那个点与$i$点的连线使得所有内部的点都在这条线上或者右侧。$right[i]$含义类似。
现在枚举每个点作为$a$作为三角形的一个顶点,其他两个顶点设为$b,c$。那么$b,c$一定要满足$left[a]\leq c\leq right[b],left[c]\leq b\leq right[a]$.
所以如果$b$也一旦确定,那么$c$的可选个数为$right[b]-left[a]+1$,所以当$a$确定时的答案为$f(a)=\sum_{b=left[left[a]]}^{right[a]}right[b]-left[a]+1$
特殊情况是如果$left[left[a]]$跟 $a$是同一个点的时候,这时候$b$的取值是$[a+1, right[a]]$,即便这样$f(a)=\sum_{b=a+1}^{right[a]}right[b]-left[a]+1$还是多算了两个不合法的三角形,它们是 $(a,left[a],left[a])$以及$(a,left[a],a)$
code for problem1
#include <stdint.h> class TrafficCongestion {
static constexpr int kMod = 1000000007; public:
int theMinCars(int treeHeight) {
int result = 0;
while (treeHeight >= 0) {
if (treeHeight <= 1) {
result = (result + 1) % kMod;
break;
} else {
result += Pow(treeHeight - 1);
result %= kMod;
treeHeight -= 2;
}
}
return result;
} private:
static int Pow(int k) {
int64_t result = 1;
int64_t a = 2;
while (k > 0) {
if ((k & 1) == 1) {
result = result * a % kMod;
}
a = a * a % kMod;
k >>= 1;
}
return static_cast<int>(result);
}
};
code for problem2
#include <stdint.h>
#include <cstring>
#include <vector> class LISNumber {
static constexpr int64_t kMod = 1000000007;
static constexpr int64_t kMax = 36; public:
int count(const std::vector<int> &cards, int K) {
if (K < cards.back()) {
return 0;
}
int N = 0;
for (auto e : cards) {
N += e;
}
if (K > N) {
return 0;
} Initialize(); std::vector<int> f0(K + 1, 0);
std::vector<int> f1(K + 1, 0);
f0[cards.back()] = 1;
int m = cards.back();
for (int i = static_cast<int>(cards.size()) - 2; i >= 0; --i) {
int n = cards[i];
for (auto &e : f1) {
e = 0;
}
for (int k = 1; k <= K; ++k) {
if (f0[k] == 0) {
continue;
}
for (int t = 1; t <= n; ++t) {
auto b = static_cast<int64_t>(f0[k]) * split_[n][t] % kMod;
int delta_k = n - t;
for (int x = 0; x <= t && x + delta_k + k <= K; ++x) {
int b1 = static_cast<int>(b * c_[k][t - x] % kMod *
c_[m - k + 1][x] % kMod);
(f1[x + delta_k + k] += b1) %= kMod;
}
}
}
m += n;
f0 = f1;
}
return f0[K];
} private:
void Initialize() {
c_[0][0] = 1;
for (int i = 1; i <= kMax; ++i) {
c_[0][i] = 0;
}
for (int i = 1, end = kMax * kMax; i <= end; ++i) {
c_[i][0] = 1;
for (int j = 1; j <= kMax; ++j) {
c_[i][j] = (c_[i - 1][j] + c_[i - 1][j - 1]) % kMod;
}
}
memset(split_, 0, sizeof(split_));
std::vector<std::pair<int, int>> p;
for (int i = 1; i <= kMax; ++i) {
p.push_back({i, 1});
Dfs(1, i, i, &p);
p.clear();
}
} void Dfs(int depth, int begin, int sum, std::vector<std::pair<int, int>> *p) {
if (sum > kMax) {
return;
}
{
int64_t x = 1;
int n = depth;
for (size_t i = 0; i < p->size(); ++i) {
(x *= c_[n][(*p)[i].second]) %= kMod;
n -= (*p)[i].second;
}
(split_[sum][depth] += static_cast<int>(x)) %= kMod;
}
for (int i = begin, end = kMax - sum; i <= end; ++i) {
if (p->back().first == i) {
p->back().second += 1;
} else {
p->push_back({i, 1});
}
Dfs(depth + 1, i, sum + i, p); if (p->back().second > 1) {
p->back().second -= 1;
} else {
p->pop_back();
}
}
} int c_[kMax * kMax + 1][kMax + 1];
int split_[kMax + 1][kMax + 1];
};
code for problem3
#include <unistd.h>
#include <algorithm>
#include <vector> class EnclosingTriangle {
public:
long long getNumber(int m, const std::vector<int>& x,
const std::vector<int>& y) {
const int n = m << 2;
std::vector<std::pair<int, int>> all(3 * n);
std::vector<int> left(3 * n);
std::vector<int> right(3 * n);
std::vector<long long> prefix(3 * n);
{
int idx = 0;
auto Add = [&](int x0, int y0, int x1, int y1) {
int dx = x1 >= x0 ? 1 : -1;
int dy = y1 >= y0 ? 1 : -1;
int x_num = abs(x1 - x0) + 1;
int y_num = abs(y1 - y0) + 1;
for (int i = 0; i < x_num; ++i) {
for (int j = 0; j < y_num; ++j) {
all[idx] = all[idx + n] = all[idx + n + n] =
std::make_pair(i * dx + x0, j * dy + y0);
++idx;
}
}
};
Add(0, 0, 0, m - 1);
Add(0, m, m - 1, m);
Add(m, m, m, 1);
Add(m, 0, 1, 0);
}
{
auto Check = [&](const std::pair<int, int>& p1,
const std::pair<int, int>& p2) {
long long dx1 = p2.first - p1.first;
long long dy1 = p2.second - p1.second;
for (size_t i = 0; i < x.size(); ++i) {
int dx2 = x[i] - p1.first;
int dy2 = y[i] - p1.second;
if (dx1 * dy2 - dy1 * dx2 > 0) {
return false;
}
}
return true;
};
for (int i = n; i < n + n; ++i) {
{
int low = i - n + 1;
int up = i - 1;
int result = up;
while (low <= up) {
int mid = (low + up) >> 1;
if (Check(all[mid], all[i])) {
result = std::min(result, mid);
up = mid - 1;
} else {
low = mid + 1;
}
}
left[i - n] = left[i] = left[i + n] = i - result;
}
{
int low = i + 1;
int up = i + n - 1;
int result = low;
while (low <= up) {
int mid = (low + up) >> 1;
if (Check(all[i], all[mid])) {
result = std::max(result, mid);
low = mid + 1;
} else {
up = mid - 1;
}
}
right[i - n] = right[i] = right[i + n] = result - i;
}
}
prefix[0] = right[0];
for (int i = 1; i < n + n + n; ++i) {
prefix[i] = prefix[i - 1] + right[i];
}
}
long long result = 0;
for (int a = n; a < n + n; ++a) {
int c = a - left[a];
int b_left = std::max(c - left[c] + n, a + 1);
int b_right = a + right[a];
if (b_right < b_left) {
continue;
}
result += prefix[b_right] - prefix[b_left - 1];
result -= static_cast<long long>(b_right - b_left + 1) *
(c + n - b_left - 1 + c + n - b_right - 1) / 2;
if (c + n == b_right) {
// (a, c, c) and (a, c, a) are invalid.
result -= 2;
}
}
return result / 3;
}
};
topcoder srm 585 div1的更多相关文章
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
- Topcoder Srm 726 Div1 Hard
Topcoder Srm 726 Div1 Hard 解题思路: 问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和. 然后可以证明一个结 ...
- topcoder srm 714 div1
problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...
- topcoder srm 738 div1 FindThePerfectTriangle(枚举)
Problem Statement You are given the ints perimeter and area. Your task is to find a triangle wi ...
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串
Problem Statement The Happy Letter game is played as follows: At the beginning, several players ...
- Topcoder SRM 584 DIV1 600
思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...
- TopCoder SRM 605 DIV1
604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...
- SRM 585 DIV1 L2
记录dp(i, j)表示前i种卡片的排列,使得LISNumber为j的方法数. #include <iostream> #include <vector> #include & ...
随机推荐
- hibernate10--命名查询
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hiber ...
- mybits根据表自动生成 java类和mapper 文件
mybits根据表自动生成 java类和mapper 文件 我这个脑子啊,每次创建新的工程都会忘记是怎么集成mybits怎么生成mapper文件的,so today , I can't write t ...
- mysql winx64安装配置方法
1.mysql-5.7.21-winx64.zip解压到自己指定的路径 2.自己新建Data文件夹和my.ini文件 my.ini内容,直接复制修改路径即可 my.ini需要保存为ANSI格式 ,否 ...
- Matplotlib学习
决定通过一个个例子来实践并掌握Matplotlib.. 例子1. 画一个散点图,数据分布如下: import numpy as np import pandas as pd import matplo ...
- 爬虫IP代理中的http与https
之前使用代理IP,构造的proxies一直都是http模式 proxies={"http": "http://{}".format(ip)} 但是今天遇到的网站 ...
- 转 python测试框架最全资源汇总
转自: http://www.testclass.net/list/python_list_1/ xUnit frameworks(单元测试框架) frameworks 框架 unittest - p ...
- HTML02单词
form:表单action:行动(提交的路径)method:方法(提交的方式)input:输入type:类型text:文本(文本输入项)password:密码radio:单选按钮checkbox:复选 ...
- DbSet<T>().Where(e => true)之后再想Include怎么办?
DbSet<T>().Where(e => true)之后再想Include怎么办? 引用:https://www.cnblogs.com/godbell/p/7348411.htm ...
- 我了解到的新知识之---Cylance Protect是干吗的?
每家企业都会采购适合自己的杀毒软件来保护企业内的电脑处在安全的状态下,我所在的公司目前在用的是来自美国的初创企业的产品Cylance Protect.,目前这家公司已经在2018年11月份被黑莓公司收 ...
- :after和:before 伪类
1 使用伪类画三角形 .div{ margin-top: 100px; margin-left: 100px; } .div:after{ content: ''; display:inline-bl ...