2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解
这次是zay神仙给我们出的NOIP模拟题,不得不说好难啊QwQ,又倒数了~
T1 大美江湖
这个题是一个简单的模拟题。 ----zay
唯一的坑点就是打怪的时候计算向上取整时,如果用ceil函数一定要先转化成double类型(话说我就这么掉坑里了?QwQ)
测试点 1: 0 次询问,所以直接freopen一下输出文件即可得分。期望得分 10 分。
测试点 4、5: 由于保证人物不移动,而且不捡拾出生点的物资也不在出生点打怪,所以攻击 防御一定全部为初始值,耗血一定为 0 ,直接输出 q 行数据即可。期望得分 20 分。
测试点 6、7、8: 地图上没有怪物,就不需要计算耗血那个复杂的式子,直接累加获得的药水即 可。期望得分 30 分。
测试点2、3、9、10: 考虑暴力模拟每一次行走,耗血的式子是可以 O(1) 计算的,而累加攻击防御 也是 O(1) 的,于是总复杂地 O(q),可以通过本题。期望得分 40 分。 需要注意的是在计算耗血的时候需要用到取整函数。如果使用 cpp 的 cmath 库里面的 ceil() 函数的话,需要注意括号里相除两数不能全为 int。
标程代码:
#include <cmath>
#include <cstdio>
#include <algorithm> const int maxn = ; char mp[maxn][maxn]; int n, m, px, py, q; struct Character {
int HP, ST, DE;
int ehp, est, ede; void print() {
printf("%d %d %d\n", this->HP, this->ST, this->DE);
} void fight() {
int x = int(ceil(1.0 * ehp / std::max(, ST - ede)));
this->HP += std::max(, x * std::max(, est - DE));
} void update(const char x) {
switch (x) {
case 'R': {
this->HP = std::max(, this->HP - );
break;
}
case 'Q': {
this->ST += ;
break;
}
case 'Y': {
this->DE += ;
break;
}
case 'M': {
fight();
break;
}
}
}
};
Character my; void mov(const int x); int main() {
freopen("mzq.in", "r", stdin);
freopen("mzq.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) {
scanf("%s", mp[i] + );
}
scanf("%d%d%d", &my.ehp, &my.est, &my.ede);
scanf("%d%d", &px, &py);
scanf("%d%d", &my.ST, &my.DE);
scanf("%d", &q);
int x;
while (q--) { scanf("%d", &x);
if (x == ) {
my.print();
} else {
x = ;
scanf("%d", &x);
mov(x);
}
}
return ;
} void mov(const int x) {
switch (x) {
case : {
--py;
break;
}
case : {
++py;
break;
}
case : {
--px;
break;
}
case : {
++px;
break;
}
default: {
puts("I AK IOI");
break;
}
};
my.update(mp[px][py]);
}
我改完之后的代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
char ch=getchar();
int a=,x=;
while(ch<''||ch>'')
{
if(ch=='-') x=-x;
ch=getchar();
}
while(ch>=''&&ch<='')
{
a=(a<<)+(a<<)+(ch-'');
ch=getchar();
}
return a*x;
}
int n,m,hp_e,st_e,de_e,st_m,de_m,hp_m;
int x,y,q,cz,where; //从(x,y)开始走
char a[][];
int fight()
{
int ans=ceil(1.0*hp_e/(max(,st_m-de_e))); //注意先转化成double类型
return max(,(int)ans*max(,st_e-de_m));
}
int main()
{
freopen("mzq.in","r",stdin);
freopen("mzq.out","w",stdout);
n=read();m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
cin>>a[i][j]; //地图
hp_e=read();
st_e=read();
de_e=read();
x=read();y=read(); //从(x,y)开始走
st_m=read();
de_m=read();
q=read();
for(int i=;i<=q;i++)
{
cz=read();
if(cz==) //查询
printf("%d %d %d\n",hp_m,st_m,de_m);
else //移动
{
where=read();
if(where==) y--; //向左走
if(where==) y++; //向右走
if(where==) x--; //向上走
if(where==) x++; //向下走
if(a[x][y]=='.') continue;
if(a[x][y]=='R') hp_m-=; //回血
if(hp_m<) hp_m=; //小于10的话回到0
if(a[x][y]=='Q') st_m+=; //加5攻击力
if(a[x][y]=='Y') de_m+=; //加5防御力
if(a[x][y]=='M') hp_m+=fight(); //打怪
}
}
return ;
}
T2 腐草为萤
子任务 1: 只有一个点,所以只有 {1} 这一种集合,于是答案为 1。期望得分 5 分。
子任务 2、3: 爆搜,枚举所有可能的集合,然后计算答案。 由于每个点只有选进集合或不选两种可能,所以一共有 2 n 个集合,然后可以 O(n) 的去检验集合是否合法,顺便统计答案。于是总复杂度 O(2 n×n)。期望得分 25分。
子任务 4、5: 考虑 DP。设 fu 是以 u 为根的子树的答案。 如果 u 没有孩子,那么 fu = uT。 如果 u 只有一个孩子 v,那么要么选 u 不选 u 的子孙,要么不选 u。不选 u 的答案即为 fv,选 u 的答案即为 u T。两种情况加起来就是 fu。 如果 u 有两个孩子 x,y。考虑要么选 u,要么只选 x 的子树内的元素,要么 只选 y 的子树内的元素,要么既选 x 内的元素又选 y 内的元素但不选 u。前三种 情况的答案易得。现在考虑第四种情况的答案。设 s 是 x 子树内的某个集合。考 虑无论 y 的子树内怎么选,再加上 s 都是合法的,因为 y 和 x 之间没有祖先后 代关系且 s 在 x 之内。设 gu 是以 u 为根能选择的集合个数,那么一共有 gy 个 集合选择 s 以后依旧合法,设 s 的权值和为 ws,于是 s 的贡献即为 ws×gy。由于 fx 为 x 子树内所有可能集合的权值和,所以可以发现 ∑ws = fx 。于是 x 子树内 的集合对答案的总贡献是 fx×gy。同理,y 子树内的集合对答案的贡献是 fy×gy。 于是 fu=fy×gx+fx×gy+fx+fy+u T。gu=gx×gy+gx+gy+1。时间复杂度O(n),期望得分 30 分。
子任务6、7: 虑在遍历子节点的时候,已经遍历了一些子节点,现在新加入了一个子节点。 由于新加入一个子节点与之前遍历的子节点没有祖先后代关系,于是可以之前遍历 过得子树看成一棵子树,然后问题就变成了子任务4、5。期望得分 40 分。 需要注意的是由于读入规模达到了10e6左右,需要普通的读入优化。
标程代码:
#include <cstdio> typedef long long int ll; const int maxn = ;
const int MOD = ; template <typename T>
inline void qr(T &x) {
char ch;
do { ch = getchar(); } while ((ch > '') || (ch < ''));
do { x = (x << ) + (x << ) + (ch ^ ); ch = getchar(); } while ((ch >= '') && (ch <= ''));
} int n, T;
int MU[maxn], frog[maxn], gorf[maxn];
bool vis[maxn]; struct Edge {
int v;
Edge *nxt; Edge(const int _v, Edge *h) : v(_v), nxt(h) {}
};
Edge *hd[maxn]; void dfs(const int u); int main() {
freopen("dzy.in", "r", stdin);
freopen("dzy.out", "w", stdout);
qr(n); qr(T);
if (T) {
for (int i = ; i <= n; ++i) {
MU[i] = i;
}
} else {
for (int i = ; i <= n; ++i) {
MU[i] = ;
}
}
for (int i = , u, v; i < n; ++i) {
u = v = ; qr(u); qr(v);
hd[u] = new Edge(v, hd[u]);
hd[v] = new Edge(u, hd[v]);
}
dfs();
printf("%d\n", frog[] % MOD);
return ;
} void dfs(const int u) {
vis[u] = true;
for (auto e = hd[u]; e; e = e->nxt) if (!vis[e->v]) {
int v = e->v;
dfs(v);
frog[u] = (frog[u] * (gorf[v] + 1ll) % MOD) + (frog[v] * (gorf[u] + 1ll) % MOD);
gorf[u] = (gorf[u] + gorf[v] + (1ll * gorf[u] * gorf[v])) % MOD;
}
frog[u] = (frog[u] + MU[u]) % MOD;
++gorf[u];
}
T3 锦鲤抄
子任务 1: 点权都是0,于是无论怎么选答案都是 0,输出 0 即可。期望得分 5 分。
子任务 2: 爆搜,枚举所有可能的顺序,然后计算答案。 由于保证了数据随机,可以在搜索的过程中进行剪枝,效率很高,期望得分25 分。
子任务 3: 给出的是一个 DAG 。考虑对于一个 DAG 来说,一个良好的的性质就是在拓扑 序后面的点无论如何变化都无法影响到前面的点。这个题也一样。对于任意一个不 出现原图中本身入度为 0 的点的序列,只要按照拓扑序选点,就一定能取遍序列中 所有的点。 于是发现这张图上入度不为0的点事实上都可以被选择。于是我们把所有入度不 为0的点排一下序,求前k个就可以了。时间复杂度 O(nlogn),期望得分30。
子任务 4、5: 考虑DAG的情况放到普通有向图上会发生什么。 有了子任务 3 的提示,我们可以考虑把整个图缩点,将其变成一个DAG来做。 对于一个DAG,显然可以通过子任务 3 调整顺序的方式使得每个强连通分量的 选择情况除选点个数以外互不影响。故下面只讨论一个强连通分量内部的情况。 一个强连通分量显然可以看作是一棵外向树加上很多边得到的。 一棵外向树的定义:一个外向树的任意一个节点要么为叶节点,要么它与孩子 间的所有边都是由它指向孩子。 一棵外向树显然是一个 DAG 。按照之前对 DAG 上情况的说明,显然我们可以 选择除了根节点以外的任意节点。 因为一个强连通分量内部是互相连通的,于是我们不妨钦定一个点为根。 对于一个没有入度的强连通分量,我们不妨钦定点权最小的点为根。这样显然 选择的是最优的。 对于一个有入度的强连通分量,我们不妨钦定那个有入度的点为根。这样在选 择到只剩根节点的时候,因为根节点有入度,所以根节点是可以被选择的。于是这 个强连通分量可以被全部选择。这显然是最优的。 这样综合上述讨论,有入度的强连通分量可以随便选,没有入度的强连通分量 去掉最小的点权的点。剩下贪心取前 k 个就可以了。 进行一次 tarjan的复杂度是 O(n+m),选前 k 个点可以排序一下。这样总复杂 度 O(m+nlogn),期望得分 35 分。注意到复杂度瓶颈在排序上,考虑我们只需要前 k 大而不需要具体前 k 个之间的大小关系,于是使用 std::nth_element()函数可 以将复杂度降至 O(n+m)。期望得分 40 分。注意,输入规模到了 10e7 级别,需要 fread 来实现读入优化。
标程代码:
#include <cstdio>
#include <algorithm>
#include <functional>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif typedef long long int ll; namespace IPT {
const int L = ;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, , L, stdin);
if (front == end) return -;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '') || (ch < '')) lst = ch, ch=IPT::GetChar();
while ((ch >= '') && (ch <= '')) x = (x << ) + (x << ) + (ch ^ ), ch = IPT::GetChar();
if (lst == '-') x = -x;
} const int maxn = ; struct Edge {
int v;
Edge *nxt; Edge(const int _v, Edge *h) : v(_v), nxt(h) {}
};
Edge *hd[maxn]; int n, m, k, vistime, top, scnt;
int MU[maxn], dfn[maxn], low[maxn], stack[maxn], belong[maxn], minv[maxn];
bool instack[maxn], haveind[maxn]; void tarjan(const int u); int main() {
freopen("zay.in", "r", stdin);
freopen("zay.out", "w", stdout);
qr(n); qr(m); qr(k); MU[] = ;
for (int i = ; i <= n; ++i) qr(MU[i]);
for (int i = , u, v; i <= m; ++i) {
u = v = ; qr(u); qr(v);
hd[u] = new Edge(v, hd[u]);
}
for (int i = ; i <= n; ++i) if (!dfn[i]) {
tarjan(i);
}
for (int u = ; u <= n; ++u) {
for (auto e = hd[u]; e; e = e->nxt) if (belong[u] != belong[e->v]) {
haveind[belong[e->v]] = true;
}
}
for (int i = ; i <= scnt; ++i) if (!haveind[i]) {
MU[minv[i]] = ;
}
std::nth_element(MU + , MU + + k, MU + + n, std::greater<int>());
int ans = ;
for (int i = ; i <= k; ++i) {
ans += MU[i];
}
printf("%d\n", ans);
return ;
} void tarjan(const int u) {
dfn[u] = low[u] = ++vistime;
instack[stack[++top] = u] = true;
for (auto e = hd[u]; e; e = e->nxt) {
int v = e->v;
if (!dfn[v]) {
tarjan(v);
low[u] = std::min(low[u], low[v]);
} else if (instack[v]) {
low[u] = std::min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
int v, &_mv = minv[++scnt];
do {
instack[v = stack[top--]] = false;
belong[v] = scnt;
if (MU[v] < MU[_mv]) _mv = v;
} while (v != u);
}
}
2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解的更多相关文章
- 2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解
看到Day 2的题真的想打死zay了,忒难了QwQ~ T1 江城唱晚 这明显是个求方案数的计数问题,一般的套路是DP和组合数学. 正如题目中所说,这个题是一个 math 题. ----zay ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- 2019.7.9 校内测试 T3 15数码问题
这一次是交流测试?边交流边测试(滑稽 15数码问题 大家应该都玩过这个15数码的游戏吧,就在桌面小具库那里面哦. 一看到这个题就知道要GG,本着能骗点分的原则输出了 t 个无解,本来以为要爆零,没想到 ...
- 2021.9.20考试总结[NOIP模拟57]
(换个编辑器代码就SB地不自动折叠了.. T1 2A 考察快读的写法. $code:$ T1 #include<bits/stdc++.h> #define scanf SCANF=sca ...
- 2019.7.9 校内测试 T2 极值问题
这一次是交流测试?边交流边测试(滑稽 极值问题 乍一看这是一道数学题,因为1e9的数据让我暴力的心退却. 数学又不好,不会化简式子嘞,咋办? 不怕,咱会打表找规律.(考场上真的是打表找出了规律,打表打 ...
- 2019.7.9 校内测试 T1挖地雷
这一次是交流测试?边交流边测试(滑稽 挖地雷 这个题是一个递推问题. 首先我们看第一个格子,因为它只影响了它的上面和右上面这两个地方是否有雷. 我们可以分3种情况讨论: 1. 第一个格子的数字是2: ...
- 2019.6.28 校内测试 T4 【音乐会】达拉崩吧·上
考试的一道附加题~ 一看题目描述:把区间[l,r]里每个数异或上x,求区间[l,r]里所有数的异或和,这明显的要用数据结构或RMQ吧. 恩,所以正解就是线段树啦,至于树状数组行与否,不知道~ wate ...
- 【8.20校内测试】【DP】【二分+贪心】
一开始想的贪心,可是发现贪心的问题太多了啊!只能保证当前最优,全局完全无法考虑. 所以正解是dp.预处理出前缀和,枚举每个区间,在每个点记录$now[i]$表示以$i$这个塔结尾的塔组目前的高度.$d ...
- 2019.6.28 校内测试 T3 【音乐会】道路千万条
大眼一看最下面的题意解释的话,发现这和洛谷P1310表达式的值挺像的,大概都是给定一些运算符号,让最后的表达式为true的概率,为false的概率啥的QwQ~: 然后这个题嘛?就是在所有的运算符中提溜 ...
随机推荐
- S02_CH16 等精度频率计实验
S02_CH16 等精度频率计实验 在了解了AXI总线之后,今天我们自己动手设计一个带AXI4-Lite总线的IP,来完成频率计的实验. 频率计虽然小,但是也算五脏俱全,涉及到zynq的方方面面,比如 ...
- 复习最短路 spfa+dijstra堆优化
题目很简单,, 但是wa了三次,, 用<vector>之前一定要记得clear()...简单说下 spfa的问题 和bell_forman有点类似 每次取出一个点 然后更新 并把更新了的节 ...
- HTML中由于DIV(块元素)浮动,导致的父元素高度塌陷问题的解决方案
费话不多说,直接上问题: 1.开始时,页面只有两个DIV的嵌套(见图) 运行结果是: 现在看运行的是正常的,但是当我设置让 class="box2" 的DIV浮动时 运行结果是这样 ...
- Node.js Express项目搭建
讲干货,不啰嗦,Express 是一个简洁而灵活的 node.js Web应用框架,使用 Express 可以快速地搭建一个完整功能的网站.本教程介绍如何从零开始搭建Express项目. 开发环境:w ...
- Java秒杀实战 (四)JMeter压测
转自:https://blog.csdn.net/qq_41305266/article/details/81071278. 一.JMeter入门 下载链接 http://jmeter.apache. ...
- LeetCode 滑动窗口题型整理
一.滑动窗口题型模板 /* * 滑动窗口类型: 模板 */ public List<Integer> slideWindowMode(String s, String t) { // 1 ...
- JavaSpring【一、概述】
主要内容 JavaSpring[一.概述] JavaSpring[二.IOC] JavaSpring[三.Bean] JavaSpring[四.Bean管理注解实现] JavaSpring[五.AOP ...
- briup_JDBC_自建工具类
1.操作的环境 STS,mysql,oracle orcle 所操作的数据库名为 ORCL 表为 m_stu 表结构如下 mysql 的表为:my_stu 表结构如下 工具类完整代码 package ...
- web开发:jquery高级
一.jq选择器 二.属性操作 三.jq轮播图 四.样式操作 五.jq动事件 六.jq动画 七.自定义动画 八.jq动画案例 一.jq选择器 - css3语法选择器 ```js$('css3选择器位') ...
- Hadoop_18_MapRduce 内部的shuffle机制
1.Mapreduce的shuffle机制: Mapreduce中,map阶段处理的数据如何传递给Reduce阶段,是mapreduce框架中最关键的一个流程,这个流程就叫shuffle 将mapta ...