EOJ Monthly 2018.2
A. 坑爹的售票机
题意
用\(1,5,10,25,50,100\)的纸币买\(n\)张单价为\(p\)的船票,且一次性最多买\(k\)张,求钱数恰好时最少需要多少张纸币。
Hard: \(n,k,p\leq 10^9\)
思路
Easy: dp
Hard: dp + 瞎搞
当钱数过大或者张数过多时,(由直觉)其中的大部分都是遵循一定的规律来取的,只有剩余的一小部分需要dp.
Code
Easy
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 10010
using namespace std;
typedef long long LL;
int a[6] = {1,5,10,20,50,100}, dp[maxn], dp2[maxn];
int main() {
int n, k, p;
scanf("%d%d%d", &n, &k, &p);
int lim = k*p;
F2(i, 1, lim) {
int minn = INT_MAX;
F(j, 0, 6) {
if (i-a[j]<0) break;
minn = min(minn, dp[i-a[j]]);
}
dp[i] = minn+1;
}
F2(i, 1, n) {
int minn = INT_MAX;
F2(j, 1, k) {
if (i-j<0) break;
minn = min(minn, dp2[i-j]+dp[j*p]);
}
dp2[i] = minn;
}
printf("%d\n", dp2[n]);
return 0;
}
Hard
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long LL;
int a[6] = {1,5,10,20,50,100}, dp[1010];
LL dp2[1010], val[20];
int main() {
LL n, p; int k;
scanf("%lld%d%lld", &n, &k, &p);
F(i, 1, 1000) {
int minn = INT_MAX;
F(j, 0, 6) {
if (i-a[j]<0) break;
minn = min(minn, dp[i-a[j]]);
}
dp[i] = minn+1;
}
F2(i, 1, k) {
LL x = i * p;
val[i] = x/1000*10 + dp[x%1000];
}
LL ans = inf;
F2(i, 1, 1000) {
LL minn = inf;
F2(j, 1, k) {
if (i-j<0) break;
minn = min(minn, dp2[i-j]+val[j]);
}
dp2[i] = minn;
ans = min(ans, n/i*dp2[i]+dp2[n%i]);
}
printf("%lld\n", ans);
return 0;
}
B. 无聊的游戏
题意
给定一棵树,两人轮流从树中选取一个度数不为 0 的结点 (度数为 0 则不与任何边相连) 将其与其相连的边删去,谁最终无法删去结点,则谁败。问是否先手必胜?
思路
状压dp.
对删去的点进行状压,记录是必胜态还是必败态,记忆化搜索进行转移。
后继全部是必胜态的状态为必败态,后继中有一个是必败态的状态为必胜态。
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 1100000
using namespace std;
typedef long long LL;
int n, dp[maxn], mp[22][22];
bool vis[maxn];
bool dfs(int state) {
if (vis[state]) return dp[state];
vis[state] = true;
F(i, 0, n) {
if (!(state&(1<<i))) {
F(j, 0, n) {
if (!(state&(1<<j)) && mp[i][j]) {
bool ret = dfs(state|(1<<i));
if (!ret) return dp[state] = 1;
}
}
}
}
return 0;
}
int main() {
scanf("%d", &n);
F(i, 1, n) {
int u, v;
scanf("%d%d", &u, &v); --u, --v;
mp[u][v] = mp[v][u] = true;
}
if (dfs(0)) puts("First");
else puts("Second");
return 0;
}
C. 贪吃的 xjj 和贪心的 oxx
题意
求 \(S=\{a_1,a_2,\ldots,a_n\}\) 这一多重集的一个非空子集 \(S'=\{a_{i_1}, a_{i_2}, \ldots, a_{i_k} \}\),使得
\]
记多重集 \(Sum(A)\) 表示多重集 \(A\) 所有元素的和。特别地,\(Sum(\varnothing)=0\)。
题解
无论什么情况答案都为 Yes
,方法为将原序列从大到小排序,贪心地放两堆,每次往少的一堆里放新的一盒,最终取少的一堆即可。
正确性显见:对于多的一堆,取走其中数量最少的一盒(即刚刚放入的一盒),则其总数必然少于少的一堆,否则这一盒不会被放入。
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 1000010
using namespace std;
typedef long long LL;
int a[maxn], id[maxn];
bool cmp(int x, int y) { return a[x]>a[y]; }
int main() {
int n;
LL x=0, y=0;
vector<int> v1,v2;
scanf("%d", &n);
F(i, 0, n) scanf("%d", &a[i]), id[i] = i;
sort(id, id+n, cmp);
F(i, 0, n) {
if (x<=y) {
v1.push_back(id[i]+1);
x += a[id[i]];
}
else {
v2.push_back(id[i]+1);
y += a[id[i]];
}
}
puts("Yes");
if (x <= y) {
printf("%d\n", v1.size());
sort(v1.begin(), v1.end());
for (auto x : v1) printf("%d ", x); puts("");
}
else {
printf("%d\n", v2.size());
sort(v2.begin(), v2.end());
for (auto x : v2) printf("%d ", x); puts("");
}
return 0;
}
D. 黑心的出租车
题意
给定一个森林,从\(1\)号点出发,遍历森林中所有的点最后回到\(1\)号点。
大巴可以在有边相连的两点间往返,而出租车可以在任意两点间往返。
要求:乘出租车次数最少的情况下,乘大巴次数也最少,求两个次数。
思路
如果只有一棵树,显然,次数为\(0,2(n-1)\)
如果有多棵树,那么:
- 出租车次数即联通块个数;
- 每棵树内的遍历可以到叶子就结束(换乘出租车到另一棵树),而不用回到最初的点。也即可以省略一段回头路。要大把次数最少,则要省略的路径最长,即要找一条最长的路,一端作为根,一端作为叶子。显然,这一条最长的路即为 直径。
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 100010
using namespace std;
typedef long long LL;
struct Edge { int to, ne; }edge[maxn<<1];
int ne[maxn], dep1[maxn], dep2[maxn], fa[maxn], tot, vis[maxn], sz[maxn];
vector<int> v[maxn];
void add(int u, int v) {
edge[tot] = {v, ne[u]};
ne[u] = tot++;
}
void dfs(int u, int fa, int d, int* dep) {
dep[u] = d;
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (v == fa) continue;
dfs(v, u, d+1, dep);
}
}
inline int find(int x) { return fa[x]==x ? x : fa[x]=find(fa[x]); }
inline void unionn(int u, int v) {
u = find(u), v = find(v);
if (sz[u] < sz[v]) swap(u, v);
fa[v] = u, sz[u] += sz[v];
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
memset(ne, -1, sizeof ne);
F2(i, 1, n) fa[i] = i, sz[i] = 1;
F(i, 0, k) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
unionn(u, v);
}
int cnt=0;
F2(i, 1, n) {
if (!vis[find(i)]) {
vis[find(i)] = ++cnt;
}
v[vis[find(i)]].push_back(i);
}
if (cnt==1) printf("%d %d\n", 0, k<<1);
else {
int ans = 0;
F2(i, 1, cnt) {
int u = v[i][0];
dfs(u, -1, 0, dep1);
for (auto x : v[i]) if (dep1[x]>dep1[u]) u = x;
dfs(u, -1, 0, dep2);
for (auto x : v[i]) if (dep2[x]>dep2[u]) u = x;
ans += (v[i].size()-1)*2-dep2[u];
}
printf("%d %d\n", cnt, ans);
}
return 0;
}
E. 出老千的 xjj
题目描述
玩了一天的 oxx 和 xjj 精力不减,晚上回到宾馆后决定玩一种卡牌游戏。
游戏规则很简单:一开始,每人手中有若干不同的牌。在每一回合中,两人轮流先手,先手可以打出 x 张任意相同的牌,随后两人轮流出牌,每次打出 x 张任意相同的牌,直至双方都不出牌,该回合结束(一方不出牌时另一方可以继续出牌直至不出牌)。下一回合中换为另一人先手,直至某一回合中一人打完手上所有牌。先打完所有牌的获胜。
xjj 出了把老千,使得自己拿到了 k 张相同的牌,她骄傲地向 oxx 炫耀:“我这牌稳赢了,让你先手。看看你那寒酸样,再给你额外几张万能牌,可以代替任何一张牌。”
机智的 oxx 立刻发现了自己胜利的希望,他想知道他至少拿到几张万能牌就可以赢得游戏。oxx 在第一回合中是先手。
题解
当牌总数小于等于 \(k\) 时,只需一张一张出即可,因此答案为 \(0\)。
当牌总数大于 \(k\) 时,需要每次出 \(x\) 张,且 \(x\) 不整除 \(k\),即加上万能牌后所有牌数量的\(gcd\) 要不为 \(k\) 的约数。
对于每次枚举的 \(p\),通过前缀和可以求出数量在 \((pi,p(i+1)]\) 之间堆数的个数 \(num\) 以及总数量和 \(sum\),那么需要 \(num\cdot p(i+1)-sum\) 张万能牌,最后求和即可。总复杂度 \(O(nlogn)\)。前缀和数组注意开到 \(2\cdot 10^6\)。
还可以进行进一步优化:只需要枚举所有素数即可,对于 \(k\) 的素因子 \(p\),则取 \(p^i\),最小的 \(i\) 使得 \(p^i\) 不能整除 \(k\)。
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 3000000
#define inf 0x3f3f3f3f3f3f3f3f
typedef long long LL;
int cnt[maxn+10], maxx, prime[maxn], tot;
LL sum[maxn+10];
bool check[maxn+10];
using namespace std;
void init() {
F2(i, 2, maxx) {
if (!check[i]) prime[tot++] = i;
F(j, 0, tot) {
if (i*prime[j]>maxx) break;
check[i*prime[j]] = true;
if (i%prime[j]==0) break;
}
}
}
LL update(LL p, LL k) {
LL ret = p*p;
while (!(k%ret)) ret *= p;
return ret;
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
F(i, 0, n) {
int x;
scanf("%d", &x);
++cnt[x];
sum[x] += x;
maxx = max(maxx, x);
}
F2(i, 1, maxn) cnt[i] += cnt[i-1], sum[i] += sum[i-1];
if (sum[maxn] <= k) { puts("0"); return 0; }
init();
LL ans = inf;
F(i, 0, tot) {
LL p = prime[i];
if (!(k%p)) p = update(p, k);
LL temp = 0;
int lim = (maxx+p-1) / p;
if (lim==1) temp = 1LL * n * p - sum[maxx];
else {
F(j, 0, lim) {
temp += 1LL * (cnt[p*(j+1)]-cnt[p*j]) * p*(j+1) - (sum[p*(j+1)]-sum[p*j]);
}
}
ans = min(ans, temp);
}
printf("%lld\n", ans);
return 0;
}
F. 回家咯
思路
列方程解方程
Code
#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long LL;
int main() {
int x1,x2,x3;
scanf("%d%d%d", &x1, &x2, &x3);
double c3=1.0*(x3-x1)/2,
c1 = x2-c3,
c2 = x1-c1;
if (c2<=0 || c1<=0 || c3<=0) puts("Wrong");
else printf("%.2f\n", c1);
return 0;
}
EOJ Monthly 2018.2的更多相关文章
- EOJ Monthly 2018.8 D. Delivery Service-树上差分(边权/边覆盖)(边权转点权)(模板题)
D. Delivery Service 单测试点时限: 2.5 秒 内存限制: 512 MB EOJ Delivery Service Company handles a massive amount ...
- EOJ Monthly 2018.7
准备继续大学acm啦 又要开始愉快的码码码啦 第一次在华东师大OJ上面做题 看来EOJ上的积分体质是假的,我怎么一把上红??? A.数三角形 神tm的防AK题放在A,出题人很不友好啊... 先写了个暴 ...
- EOJ Monthly 2018.4
A. ultmaster 的小迷妹们 Time limit per test: 2.0 seconds Memory limit: 256 megabytes ultmaster 男神和他的小迷妹们准 ...
- EOJ Monthly 2018.4 (E.小迷妹在哪儿(贪心&排序&背包)
ultmaster 男神和小迷妹们玩起了捉迷藏的游戏. 小迷妹们都希望自己被 ultmaster 男神发现,因此她们都把自己位置告诉了 ultmaster 男神,因此 ultmaster 男神知道了自 ...
- [EOJ Monthly 2018.10][C. 痛苦的 01 矩阵]
题目链接:C. 痛苦的 01 矩阵 题目大意:原题说的很清楚了,不需要简化_(:з」∠)_ 题解:设\(r_i\)为第\(i\)行中0的个数,\(c_j\)为第\(j\)列中0的个数,\(f_{i,j ...
- EOJ Monthly 2018.11 D. 猜价格
猜价格 分两种情况讨论: k≤n,先猜至多 k 次 1,由于回答 <1 肯定是假的,所以可以把剩余系下是哪次错试出来,然后用至多 n 次搞定. k>n,每个数都猜两次,如果两次结果不一样, ...
- 【EOJ Monthly 2018.7】【D数蝌蚪】
https://acm.ecnu.edu.cn/contest/92/problem/D/ D. 数蝌蚪 Time limit per test: 2.0 seconds Memory limit: ...
- EOJ Monthly 2018.7 B.锐角三角形(数学几何+思维)
描述 是否存在面积为S/2的整点锐角三角形?存在输出Yes并输出三个整点坐标,否则输出No. 注意如果存在输出的坐标必须在long long范围内. Input 第一行一个整数S(1<=S< ...
- EOJ Monthly 2018.11 猜价格 (模拟)
分三种情况: 1.k=1.此时每次都说反话,反着二分即可. 2.1<k <= n.那么在前n次问答中一定会出现一次错误,通过不断输出1找出那个错误发生的位置(若回答是>那这就是错误) ...
随机推荐
- OpenFaceswap 入门教程(3): 软件参数篇!
OpenFaceswap 的使用可以说是非常简单,只要稍加点拨就可以学会,厉害一点的人根本不需要教程,直接自己点几下就知道了.看了前面安装篇和使用篇.我想大多数人应该会了. 当学会了使用之后,你可能对 ...
- DeepFaceLab进阶(4):通过Colab免费使用Tesla K80 跑模型!
当学会了换脸软件DeepFaceLab基本使用,各种参数配置,各有优化技能之后.唯一约束你的可能是电脑配置. CPU能跑,但是慢到怀疑人生,低配模型都得跑一周 低配显卡,显存不够,H128 根本就跑不 ...
- php中 为什么验证码 必须要开启 ob_clean 才可以显示
用ob_clean(),将前面的输出都清除就OK了 这表示你的程序前面有输出,<?php 前有空格.空行.文件有BOM头 ob_clean(); header("content-typ ...
- python-字符串数据类型内置方法
字符串类型内置方法 (str) 用途:描述性质的东西,如人的名字.单个爱好.地址.国家等 定义:使用单引号(' ').双引号(" ").三单引号(''' ''').三双引号(&qu ...
- [原]sencha touch之NavigationView
还是直接上代码,都是基本的几个容器控件,没什么还说的 Ext.application({ name:'itkingApp', launch:function(){ var view =Ext.crea ...
- Careercup - Microsoft面试题 - 4639756264669184
2014-05-12 06:42 题目链接 原题: Write your own regular expression parser for following condition: az*b can ...
- 12、jQuery知识总结-2
1.避免冲突 jQuery 使用 $ 符号作为 jQuery 的简介方式 <html> <head> <script type="text/javascript ...
- 61、请求数据进行gizp压缩
1.请求时进行头部处理 /** * 设置通用消息头 * * @param request */ public void setHeader(HttpUriRequest request) { // r ...
- 【Rotate Image】cpp
题目: You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwis ...
- Python Unicode与中文处理
转自:http://blog.csdn.net/dao123mao/article/details/5396497 python中的unicode是让人很困惑.比较难以理解的问题,本文力求彻底解决这些 ...