传送门

A - Circle

签到。

B - Echo

签到到。

C - Average Length

要卡下精度,可用二分或者long double来搞。

Code
/*
* Author: heyuhhh
* Created Time: 2019/11/16 20:04:44
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 10;
const double eps = 1e-6;
int n;
struct Point{
int x, y;
}p[N];
int a[N];
double dis(Point A, Point B) {
double tmp = 1.0 * (A.x - B.x) * (A.x - B.x) + 1.0 * (A.y - B.y) * (A.y - B.y);
double l = 0, r = tmp, mid;
for(int i = 1; i <= 500; i++) {
mid = (l + r) / 2;
if(mid * mid < tmp) l = mid;
else r = mid;
}
return r;
}
void run(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> p[i].x >> p[i].y;
for(int i = 1; i <= n; i++) a[i] = i;
double ans = 0;
int tot = 0;
do {
++tot;
for(int i = 2; i <= n; i++) {
ans += dis(p[a[i]], p[a[i - 1]]);
}
} while(next_permutation(a + 1, a + n + 1));
ans = ans / tot;
cout << ans;
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}

D - Knight

题意:

现在有个棋子位于\((0,0)\)点,当棋子位于\((i,j)\)时,可以跳向\((i+1,j+2),(i+2,j+1)\)这两个格子。

问有多少种方式可以到点\((x,y)\)。

思路:

由于\(x,y\leq 10^6\),显然直接\(dp\)不行。

然后找规律,从终点往回跳来模拟一下,发现最终会形成多条斜率为\(1\)的直线,每跳直线上面相关点的答案为一个组合数。

然后发现最终\((0,0)\)点所在的层数为\(\frac{x+y}{3}\),最终答案就是\(\frac{x+y}{3}\choose t\)。

细节在纸上画一下就出来了。

Code
/*
* Author: heyuhhh
* Created Time: 2019/11/16 20:26:13
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 15, MOD = 1e9 + 7; int fac[N]; ll qpow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
} int C(int n, int m) {
return 1ll * fac[n] * qpow(fac[n - m], MOD - 2) % MOD * qpow(fac[m], MOD - 2) % MOD;
} void run(){
fac[0] = 1;
for(int i = 1; i < N; i++) fac[i] = 1ll * fac[i - 1] * i % MOD;
int x, y;
cin >> x >> y;
if((x + y) % 3 != 0) {
cout << 0;
return;
}
int t = (x + y) / 3;
if(y - t >= 0 && y - t <= t) {
cout << C(t, y - t);
} else cout << 0;
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}

E - All-you-can-eat

题意:

现在有\(n\)盘菜,每盘菜需要\(a_i\)的时间去吃,有\(b_i\)的美味度。

现在有如下规则:

  • 点了一盘菜之后,只能将其吃完后才能点下一盘菜。
  • \(T\)时刻过后就不能再点菜了,但是依旧可以吃菜。
  • 每种菜只能点一次。

最后问最后能够得到的最大美味度是多少。

思路:

  • 注意比较重要的一点,无论最终点菜顺序是什么,我们都可以将某一份菜安排在\(T\)时刻来点。
  • 那么之后问题就变得很简单了:总共有\(T-1\)时刻,然后相当于一个背包问题,直接\(dp\)需要\(O(n^2)\)。
  • 但是我们需要枚举哪个菜在最后点,所以总复杂度为\(O(n^3)\)的,显然时间复杂度不能承受。
  • 由于我们只关注的是某一个菜不选,那么我们可以预处理一个前后缀的\(dp\),\(dp1[i][j]\)表示\(1\)~\(i\)的物品中,总时间不超过\(j\)的最大美味度,\(dp2[i][j]\)同理。
  • 最终时间复杂度为\(O(n^2)\)。

直接来做这个题因为可以超出时间限制,所以不好定义状态,但是钦定最后一个位置后问题就得到转换。

前后缀\(dp\)预处理还是比较巧妙QAQ。

Code
/*
* Author: heyuhhh
* Created Time: 2019/11/18 15:30:25
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 3005; int n, t;
int a[N], b[N];
int dp1[N][N], dp2[N][N]; void run(){
for(int i = 1; i <= n; i++) cin >> a[i] >> b[i];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= t - 1; j++) {
dp1[i][j] = dp1[i - 1][j];
if(j >= a[i])
dp1[i][j] = max(dp1[i][j], dp1[i - 1][j - a[i]] + b[i]);
}
}
for(int i = n; i >= 1; i--) {
for(int j = 1; j <= t - 1; j++) {
dp2[i][j] = dp2[i + 1][j];
if(j >= a[i])
dp2[i][j] = max(dp2[i][j], dp2[i + 1][j - a[i]] + b[i]);
}
}
int ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= t - 1; j++) {
ans = max(ans, dp1[i - 1][j] + dp2[i + 1][t - 1 - j] + b[i]);
}
}
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> t) run();
return 0;
}

 

这个题还有更巧妙的解法:假设我们知道了最后点的哪些菜,那么显然我们总能把耗时最多的安排在\(T\)时刻来点。

这时问题转换地更进一步:假设钦定了最后一位,那么前面只能选择耗时不超过它的。

所以直接处理出上面的\(dp1[i][j]\),同时维护一个后缀最大值即可。

Code
/*
* Author: heyuhhh
* Created Time: 2019/11/18 15:30:25
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 3005; int n, t;
struct node {
int a, b;
bool operator < (const node &A) const {
return a < A.a;
}
}p[N];
int maxv[N];
int dp[N][N]; void run(){
for(int i = 1; i <= n; i++) cin >> p[i].a >> p[i].b;
sort(p + 1, p + n + 1);
for(int i = n; i >= 1; i--) maxv[i] = max(maxv[i + 1], p[i].b);
int ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= t - 1; j++) {
dp[i][j] = dp[i - 1][j];
if(j >= p[i].a) dp[i][j] = max(dp[i][j], dp[i - 1][j - p[i].a] + p[i].b);
}
ans = max(ans, dp[i][t - 1] + maxv[i + 1]);
}
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> t) run();
return 0;
}

F - Laminate

题意:

现在有\(n\)个柱子排在一起,每个柱子有个高度\(h_i,0\leq h_i\leq 10^9\)。

现在有至多\(k\)次机会任意修改某些柱子的高度。

之后会执行操作:每次可以横向消去一段连续的柱子。问最终最少的操作次数是多少。

思路:

这个题感觉直接做也没什么思路...太菜了555。

就感觉问题很抽象,考虑很多情况,一般这种感觉将问题形象化、具体化是解题的关键,比如这个题,我们考虑\(k=0\)的情况,那么最终的答案为:

\[\sum_{i=1}^{n}max(0,h_i-h_{i-1})
\]

然后有个结论:如果修改一根柱子,假设其位置为\(i\),那么最终其高度在\([h_{i-1},h_{i+1}]\)之间是最优的。

这个结论较为显然,那么我们可以直接钦定:修改操作即令\(h_i=h_{i-1}\)。

进一步观察可以发现,操作等价于删除一根柱子。

这个时候解法就呼之欲出了,可令\(dp[i][j]\)表示前\(i\)根柱子,保留\(j\)根的最小操作次数。

那么有转移:\(dp[i][j] = min\{dp[k][j-1]+max(0,h_i-h_k),j<i\}\)。

直接\(O(n^3)\)来搞就没了。

P.S:这个可以将后面\(max\)操作打开,然后用树状数组维护两个值来优化,复杂度可以达到\(O(n^2logn)\)

Code
/*
* Author: heyuhhh
* Created Time: 2019/11/18 18:16:10
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 300 + 5; int n, K; int h[N];
ll dp[N][N]; void run(){
for(int i = 1; i <= n; i++) cin >> h[i];
memset(dp, INF, sizeof(dp));
dp[0][0] = 0;
for(int i = 1; i <= n - K; i++) {
for(int j = i; j <= n; j++) {
for(int k = 0; k < j; k++) {
dp[j][i] = min(dp[j][i], dp[k][i - 1] + max(0, h[j] - h[k]));
}
}
}
ll ans = INF;
for(int i = 1; i <= n; i++) ans = min(ans, dp[i][n - K]);
if(ans == INF) ans = 0;
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> K) run();
return 0;
}

AtCoder Beginner Contest 145的更多相关文章

  1. AtCoder Beginner Contest 100 2018/06/16

    A - Happy Birthday! Time limit : 2sec / Memory limit : 1000MB Score: 100 points Problem Statement E8 ...

  2. AtCoder Beginner Contest 052

    没看到Beginner,然后就做啊做,发现A,B太简单了...然后想想做完算了..没想到C卡了一下,然后还是做出来了.D的话瞎想了一下,然后感觉也没问题.假装all kill.2333 AtCoder ...

  3. AtCoder Beginner Contest 053 ABCD题

    A - ABC/ARC Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Smeke has ...

  4. AtCoder Beginner Contest 136

    AtCoder Beginner Contest 136 题目链接 A - +-x 直接取\(max\)即可. Code #include <bits/stdc++.h> using na ...

  5. AtCoder Beginner Contest 137 F

    AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...

  6. AtCoder Beginner Contest 076

    A - Rating Goal Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Takaha ...

  7. AtCoder Beginner Contest 079 D - Wall【Warshall Floyd algorithm】

    AtCoder Beginner Contest 079 D - Wall Warshall Floyd 最短路....先枚举 k #include<iostream> #include& ...

  8. AtCoder Beginner Contest 064 D - Insertion

    AtCoder Beginner Contest 064 D - Insertion Problem Statement You are given a string S of length N co ...

  9. AtCoder Beginner Contest 075 D - Axis-Parallel Rectangle【暴力】

    AtCoder Beginner Contest 075 D - Axis-Parallel Rectangle 我要崩溃,当时还以为是需要什么离散化的,原来是暴力,特么五层循环....我自己写怎么都 ...

随机推荐

  1. JavaScript 代码执行顺序

    一.先预处理后执行 在一个JavaScript文件或一个JavaScript代码块的内部,浏览器会先对代码进行预处理(编译),然后再执行. 预处理会跳过执行语句,只处理声明语句,同样也是按从上到下按顺 ...

  2. 微服务、SpringCloud、k8s、Istio杂谈

    一.微服务与SOA “微服务”是一个名词,没有这个名词之前也有“微服务”,一个朗朗上口的名词能让大家产生一个认知共识,这对推动一个事务的发展挺重要的,不然你叫微服务他叫小服务的大家很难集中到一个点上. ...

  3. Spring案例--打印机

    目录: 1.applicationContext.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> &l ...

  4. Python骚操作:Python控制Excel实现自动化办公!

    1.安装 ​ ​ 2.操作一个简单的Excel文档 操作注释及代码: ​ 操作完成后,数据存储结果如下: ​ 3. 操作简单Excel文档并添加数据格式 操作代码如下:附带数据格式的定义 ​ 操作效果 ...

  5. 使用Xmanager分析Java内存情况

    今天是想看下程序在正式环境中,内存使用回收的情况,于是开始. 1.首先下载Xmanager,Xshell,然后在Xshell-设置-隧道中设置转发X11连接到Xmanager: 2.开始布置Linux ...

  6. 6 种微服务 RPC 框架,你知道几个?

    开源 RPC 框架有哪些呢? 一类是跟某种特定语言平台绑定的,另一类是与语言无关即跨语言平台的. 跟语言平台绑定的开源 RPC 框架主要有下面几种. Dubbo:国内最早开源的 RPC 框架,由阿里巴 ...

  7. java 连缀用法

    连缀用法,即是在实例化对象时,同时为对象的属性设值. 如示例所示,在创建对象时,同时调用属性的设值函数,为属性赋值 Apple apple = new Apple() .setColor(" ...

  8. Newtonsoft.Json 序列化踩坑之 IEnumerable

    Newtonsoft.Json 序列化踩坑之 IEnumerable Intro Newtonsoft.Json 是 .NET 下最受欢迎 JSON 操作库,使用起来也是非常方便,有时候也可能会不小心 ...

  9. wpf 两个自定义控件

    wpf 两个自定义控件 一个是IP控件,一个滑动条.先看下效果图 IPControl 1.实际工作中有时需要设置IP信息,就想着做一个ip控件.效果没有window自带的好,需要通过tab切换.但也能 ...

  10. WPF的DataGrid的某个列绑定数据的三种方法(Binding、Converter、DataTrigger)

    最近在使用WPF的时候,遇到某个列的值需要根据内容不同进行转换显示的需求.尝试了一下,大概有三种方式可以实现: 1.传统的Binding方法,后台构造好数据,绑定就行. 2.转换器方法(Convert ...