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 & ...
随机推荐
- vue的组件基础
组件分为全局组件和局部组件. 组件的核心是template:所有的数据都为template服务. 父组件子组件传值:因为子组件是父组件的个标签,完全等同于添加动态属性: 然后子组件能够通过props: ...
- pro.antd.design
有关react的ui组建antd.design新推出的pro版本,最近用到了路由方面. common与routes; 首先需要在menu.js里面配置: { name: '精品', icon: 'da ...
- 学习完HTML后的5大测试题----9.18
考试题目 第一题: 布局出该效果 提示:使用DIV的border样式,调整边框粗细出现该效果,保留上边框,其它三个方向的边框需设置:border-left:100px solid transpar ...
- linux考试题改错
符号链接和硬链接有什么区别? 改:符号链接存储文件路径,可以指向不同分区文件,源文件删除后失效. 改:硬链接指向文件索引节点,仅能指向同一分区文件,源文件删除后可以访问. 请描述文件和目录9位权限位的 ...
- 这 10 款良心 Windows 软件,改变你对国产的认知
提起国产 Windows 软件,你可能首先想到的是捆绑安装.弹窗广告.卸载残留等关键词.尽管一些所谓「大厂」的确致力于拉低业界的下限,但依然有开发者坚守底线,为改变整个生态圈而默默努力.今天,少数派就 ...
- MSCKF_VIO:MSCKF的双目版本
论文:MSCKF的双目版本 Robust Stereo Visual Inertial Odometry for Fast Autonomous Flight 下载地址:点击 源码地址:https:/ ...
- 2016 Multi-University Training Contest 2题解报告
A - Acperience HDU - 5734 题意: 给你一个加权向量,需要我们找到一个二进制向量和一个比例因子α,使得|W-αB|的平方最小,而B的取值为+1,-1,我们首先可以想到α为输入数 ...
- 最全的MonkeyRunner自动化测试从入门到精通(9)
最基本脚本功能开始编写(1)Monkeyrunner和Monkey的区别 1)Monkeyrunner工具在工作站上通过API定义的特定命令和事件控制设备或模拟器(可控) 2)精确控制事件之间的事件 ...
- winform做的excel与数据库的导入导出
闲来无事,就来做一个常用的demo,也方便以后查阅 先看效果图 中间遇到的主要问题是获取当前连接下的所有的数据库以及数据库下所有的表 在网上查了查,找到如下的方法 首先是要先建立一个连接 _connM ...
- fat32转ntfs命令
1.打开电脑左下角的 “开始” 菜单2.鼠标左键单机 “运行”3.弹出横框输入 cmd 后,确定4.弹出黑框输入 convert E:/FS:NTFS 然后回车5.提示输入盘符名,也就是你输入D盘的名 ...