HGOI NOIP模拟4 题解
NOIP国庆模拟赛Day5 题解
T1 马里奥
题目描述
马里奥将要参加 NOIP 了,他现在在一片大陆上,这个大陆上有着许多浮空岛,并且其中一座浮空岛上有一个传送门,马里奥想要到达传送门从而前往 NOIP的考场。
从一座浮空岛出发,马里奥可以到达一个在水平方向和这个浮空岛相接的另一个浮空岛,他还可以使用梯子到达在这个浮空岛正上方或正下方的另一座浮空岛,但是这两个浮空岛的高度差不能超过梯子的长度。
现在,马里奥希望用最短的梯子到达传送门,请你输出梯子的最短长度。
我们把浮空岛抽象成一个二维平面,’#’代表浮空岛,’_’代表空中。
两个整数 x,y 代表传送门所在的行数和列数。
保证最下方一行全部为’#’,且传送门所在位置为’#’,
马里奥一开始在最左下方的那个浮空岛上。
输入格式
第一行两个整数 n,m,表示输入平面的行数和列数。
接下来 n 行每行一个包含 m 个字符的字符串,表示这个二维平面。
最后一行两个整数 x,y 表示传送门所在的行和列。
输出格式
输出一行一个整数,表示梯子的最小长度
样例输入输出
Simple input #1:
5 8
####____
___#_###
###__#__
______#_
########
2 4
Simple output#1:
2
数据范围和提示
对于 70%的数据:1≤n,m≤100,1≤x≤n,1≤y≤m。
对于 100%的数据:1≤n,m≤1,000,1≤x≤n,1≤y≤m。
本题时限1s,空间256MB
题解
Subtask1: 暴力dfs不优化暴力(具体不知道多暴力,反正我这个就是最暴力了)
Subtask2: 二分答案+BFS
时间复杂度 O(log n * n^2)
没什么好说了吧
代码(Subtask2 100pts)
# include<bits/stdc++.h>
# define Rint register int
using namespace std;
const int MAXN=1e3+;
int n,m,tt=;
char s[MAXN];
int a[MAXN][MAXN],x,y;
struct rec{ int x,y;};
bool vis[MAXN][MAXN];
bool check(Rint Mid)
{
queue<rec>q;
rec s; s.x=n; s.y=;
q.push(s);
memset(vis,false,sizeof(vis));
while (!q.empty()) {
rec u=q.front();q.pop(); rec v;
if (u.x==x&&u.y==y) return true;
v.x=u.x;v.y=u.y-;
if (v.x>=&&v.x<=n&&v.y>=&&v.y<=m&&a[v.x][v.y]&&(!vis[v.x][v.y])) {
if (v.x==x&&v.y==y) return true;
vis[v.x][v.y]=;
q.push(v);
}
v.x=u.x;v.y=u.y+;
if (v.x>=&&v.x<=n&&v.y>=&&v.y<=m&&a[v.x][v.y]&&(!vis[v.x][v.y])) {
if (v.x==x&&v.y==y) return true;
vis[v.x][v.y]=;
q.push(v);
}
for (int i=;i<=Mid;i++) {
v.x=u.x+i; v.y=u.y;
if (v.x>=&&v.x<=n&&v.y>=&&v.y<=m&&a[v.x][v.y]&&(!vis[v.x][v.y])) {
if (v.x==x&&v.y==y) return true;
vis[v.x][v.y]=;
q.push(v);
}
v.x=u.x-i; v.y=u.y;
if (v.x>=&&v.x<=n&&v.y>=&&v.y<=m&&a[v.x][v.y]&&(!vis[v.x][v.y])) {
if (v.x==x&&v.y==y) return true;
vis[v.x][v.y]=;
q.push(v);
}
}
}
return false;
}
int main()
{
freopen("mario.in","r",stdin);
freopen("mario.out","w",stdout);
scanf("%d%d\n",&n,&m);
for(Rint i=;i<=n;i++) {
cin>>s;
int len=strlen(s);
for (Rint j=;j<len;j++)
if (s[j]=='#') a[i][j+]=;
else a[i][j+]=;
}
scanf("%d%d",&x,&y);
int L=,R=n,Ans;
while (L<=R) {
int M=(L+R)/;
if (check(M)) Ans=M,R=M-;
else L=M+;
}
printf("%d\n",Ans);
return ;
}
T2 祭司
题目描述
马里奥在你的帮助下成功地进入了传送门,但在传送途中,传送门出了一些 故障,马里奥被传送到了一座宏伟的神殿。神殿的祭司愿意帮助马里奥修复传送 门,但是祭司现在正忙于解读古代的魔法典籍,他希望马里奥能帮他解读。古代 典籍中给出了一些变量,每个变量都有一个可能的取值范围,祭司需要把这些变 量分成两组。对于一种划分方案,对这两组变量分别求和之后做差,可能得到的 差值的绝对值的最大值就是这次划分的评级。而那个评级最小的划分是解密的关 键,祭司想让马里奥求出这个最小的评级是多少,但马里奥已经没有多少时间了, 于是他找到了你来帮忙算出这个数字。
输入格式
第一行一个整数 n,表示给出的变量个数。
接下来 n 行每行两个整数,
第 i 行的两个数 li,ri,表示第 i 个变量的取值范围 为[li, ri]。
输出格式
输出应该包含一行一个整数,表示评级的最小值。
输入输出样例
Simple input:
4
1 3
3 6
2 4
4 5
Simple output:
5
Explain:
第一和第四个变量一组,第二和第三个变量一组。
当四个变量分别取值为 (1,6,4,4)时取得该情况下的最大值 5。
数据规模和约定
对于 70%的数据:1≤n≤10。
对于 100%的数据:1≤n,m≤200;0≤li,ri≤200。
本题时限1s,空间256MB
题解:
Subtask1:理解题意暴力dfs
时间复杂度O(2^n)
代码(Subtask1 70pts):
# include <bits/stdc++.h>
using namespace std;
const int MAXN=2e2+;
int n,t[MAXN],ans;
struct rec{
int l,r;
}a[MAXN];
void check()
{
int t1,t2,Max=; t1=t2=;
for (int i=;i<=n;i++)
if (t[i]) t1+=a[i].l;
else t2+=a[i].r;
Max=max(Max,abs(t1-t2));
t1=t2=;
for (int i=;i<=n;i++)
if (t[i]) t1+=a[i].r;
else t2+=a[i].l;
Max=max(Max,abs(t1-t2));
ans=min(ans,Max);
}
void dfs(int dep)
{
if (dep==n+) { check(); return; }
t[dep]=; dfs(dep+);
t[dep]=; dfs(dep+);
}
int main()
{
freopen("priest.in","r",stdin);
freopen("priest.out","w",stdout);
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d%d",&a[i].l,&a[i].r);
ans=INT_MAX;
dfs();
printf("%d\n",ans);
return ;
}
Subtask2:Dp
Min1 表示A集合的上界之和
Min2 表示B集合的上界之和
Max1 表示A集合的下界之和
Max2 表示B集合的下界之和
Sum1 表示A集合元素上下界之和
Sum2 表示B集合元素上下界之和
答案就是求 max(|Min1-Max2|,|Min2-Max1|)
max(|Min1-Max2|,|Min2-Max1|)=max(|Min1+Max1-Max2-Max1|,|Max2+Min2-Max1-Max2|)
=max(|Sum1-(Max1+Max2)|,|Sum2-(Max1+Max2)|);<--最小化这个
其中 Max1+Max2为全集的上界,只需要维护Sum1,Sum2即可.
f[i]表示A集合上下界为i是否可能
f[i]=f[i]|f[i-(a[j].l+a[j].r)];
复杂度O(n^3)
代码(Subtask 2 100pts):
/*
Min1 表示A集合的上界之和
Min2 表示B集合的上界之和
Max1 表示A集合的下界之和
Max2 表示B集合的下界之和
Sum1 表示A集合元素上下界之和
Sum2 表示B集合元素上下界之和
答案就是求 max(|Min1-Max2|,|Min2-Max1|)
max(|Min1-Max2|,|Min2-Max1|)=max(|Min1+Max1-Max2-Max1|,|Max2+Min2-Max1-Max2|)
=max(|Sum1-(Max1+Max2)|,|Sum2-(Max1+Max2)|);<--最小化这个
其中 Max1+Max2为全集的上界,只需要维护Sum1,Sum2即可.
f[i]表示A集合上下界为i是否可能
f[i]=f[i]|f[i-(a[j].l+a[j].r)];
*/
# include <bits/stdc++.h>
using namespace std;
const int MAXN=;
struct rec{
int l,r;
}a[MAXN];
bool f[],n;
int main()
{
scanf("%d",&n);
int Sum1=,Sum2=;
for (int i=;i<=n;i++) {
scanf("%d%d",&a[i].l,&a[i].r);
Sum1+=a[i].l; Sum2+=a[i].r;
}
memset(f,false,sizeof(f));
f[]=true;
for (int i=;i<=n;i++)
for (int j=;j>=a[i].l+a[i].r;j--)
f[j]=f[j]||f[j-a[i].l-a[i].r];
int ans=INT_MAX;
for (int i=;i<=;i++) {
if (!f[i]) continue;
ans=min(ans,max(abs(Sum1-i),abs(Sum2-i)));
}
printf("%d\n",ans);
return ;
}
T3 AK
题目描述
NOIP 考场上,马里奥顺利地切掉了前两题,他只要再切掉最后一题就可以 AK 了。最后一题是这样的:给你一个数字序列,每次查询一段区间的数字和, 并且把它们都变成原来的平方。马里奥瞬间就切掉了这道题,但他觉得这道题对 于别人来说太难了。出题人在和马里奥商量后,决定在询问时只要求返回模一个 数 c = 2305843008676823040 的结果。作为另一名 NOIP 选手的你也已经切掉了 前两题,你能够解决这个修改后的问题,顺利 AK 吗?
输入格式
第一行两个整数 n,m,表示数字个数和询问个数。
接下来一行 n 个数字 ai,表示序列的初始值。
接下来 m 行,每行两个整数 l,r 表示询问区间。
输出格式
对于每次询问,你需要输出一个整数,表示对应询问的结果。
输入输出样例
Simple input:
4 4
2 3 4 5
1 2
2 3
3 4
1 4
Simple output:
5
数据规模和约定
对于 60%的数据:1≤n,m≤2^10。
对于 100%的数据:1≤n,m≤2^16;0≤ai<c。
本题时限5s,空间256MB
题解
我的分块的第一题!!!
首先发现这个东西2305843008676823040明显不是质数
考虑到luogu的某一题模数是2的几次方,也不是质数在这里做手脚
又考虑到luogu有一道上帝造题的七分钟,几次以后就不变了,
由此联想最终发现若干次(考场上用不是质数推发现28次)以后模c的值就不变了
于是想到分块+并查集 维护一个暴力。
Sum[i] 表示第i个块所有值之和,L[i]表示块i的左边界,R[i]表示块i的右边界
a[i].val表示i点的点权,a[i].bl表示i在哪个块里 bl是块的数目
并查集维护i点的右边那个还未被更新的点的位置,便于快速移动
然后register int 还有inline 快读心里作用就可以极限数据1s以内了。
这道题时限5s好像稳过
Subtask 2 100pts)
# include <bits/stdc++.h>
# define int long long
# define Rint register long long
using namespace std;
const int mo=,E=,MAXN=(<<)+;
int n,m,bl;
int f[MAXN],L[MAXN],R[MAXN],sum[MAXN],cnt[MAXN];
struct rec{
int bl,val;
}a[MAXN];
inline int read()
{
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
inline void print(Rint x)
{
if(x>) print(x/);
putchar(x%+'');
}
inline int father(Rint x)
{
if (f[x]==x) return f[x];
f[x]=father(f[x]);
return f[x];
}
inline int mul(Rint a,Rint b)
{
int res=0ll;
while (b) {
if (b&) res=(res+a)%mo;
a=(a<<)%mo; b>>=;
}
return res%mo;
}
inline int solve(Rint l,Rint r)
{
int lb=a[l].bl,rb=a[r].bl,ans=0ll;
if (lb==rb) {
for (Rint i=l;i<=r;i++)
ans=(ans+a[i].val)%mo;
return ans;
}
for (Rint i=l;i<=R[lb];i++) ans=(ans+a[i].val)%mo;
for (Rint i=r;i>=L[rb];i--) ans=(ans+a[i].val)%mo;
for (Rint i=lb+;i<=rb-;i++) ans=(ans+sum[i])%mo;
return ans%mo;
}
inline void update(Rint l,Rint r)
{
for (Rint i=l;i<=r;i=father(i+)) {
if (i>r||i==) break;
int nowbl=a[i].bl;
sum[nowbl]=(sum[nowbl]-a[i].val+mo)%mo;
a[i].val=mul(a[i].val,a[i].val)%mo; cnt[i]++;
if (cnt[i]>E) f[i]=father(i+);
sum[nowbl]=(sum[nowbl]+a[i].val)%mo;
}
}
signed main()
{
freopen("ak.in","r",stdin);
freopen("ak.out","w",stdout);
scanf("%lld%lld",&n,&m);
for (Rint i=;i<=n;i++) f[i]=i;
memset(cnt,,sizeof(cnt));
bl=; L[]=;
int POA=sqrt(n)+;
for (Rint i=;i<=n;i++) {
if (i%POA==) { R[bl]=i-; bl++; L[bl]=i; }
a[i].val=read();
a[i].bl=bl;
sum[bl]=(sum[bl]+a[i].val)%mo;
}
R[bl]=n;
Rint l,r;
while (m--) {
l=read();r=read();
print(solve(l,r)); putchar('\n');
update(l,r);
}
return ;
}
From: HGOI
Name:ljc20020730
Date: 20181005
HGOI NOIP模拟4 题解的更多相关文章
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 「题解」NOIP模拟测试题解乱写II(36)
毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...
- HZOJ 20190818 NOIP模拟24题解
T1 字符串: 裸的卡特兰数题,考拉学长讲过的原题,就是bzoj3907网格那题,而且这题更简单,连高精都不用 结论$C_{n+m}^{n}-C_{n+m}^{n+1}$ 考场上10min切掉 #in ...
- 「题解」NOIP模拟测试题解乱写I(29-31)
NOIP模拟29(B) T1爬山 简单题,赛时找到了$O(1)$查询的规律于是切了. 从倍增LCA那里借鉴了一点东西:先将a.b抬到同一高度,然后再一起往上爬.所用的步数$×2$就是了. 抬升到同一高 ...
- [NOIP模拟13]题解
A.矩阵游戏 其实挺水的? 考场上根本没有管出题人的疯狂暗示(诶这出题人有毛病吧这么简单的东西写一大堆柿子),而且推公式能力近乎没有,所以死掉了. 很显然乘法有交换率结合率所以操作顺序对最终结果没什么 ...
- 8.3 NOIP 模拟12题解
话说这次考试T1和T2是真的水,然而T1CE,T2TLE,T3CE 这不就是在侮辱我的智商啊!之前本机编译都是c++,以后要用c++11. 这次的T1就是一个大型找规律,我的规律都找出来了,但是竟然用 ...
- HZOJ 20190819 NOIP模拟26题解
考试过程: 照例开题,然后觉得三道题都挺难,比昨天难多了(flag×1),T1 dp?T2 数据结构? T3 dp?事实证明我是sb然后决定先搞T2,但是,woc,这题在说什么啊,我怎么看不懂题啊,连 ...
- [NOIP模拟26]题解
今天的考试题改自闭了……所以滚来写陈年题解. A.*****贪婪***** RT,出题人告诉我们这题要贪心. 最优的策略一定是拖到必须断的时候再断开(虽然并不知道为什么). 如果一段序列满足题目中的性 ...
- [NOIP模拟25]题解
A.字符串 Catalan数不能再裸了 #include<cstdio> #include<iostream> #include<cstring> using na ...
随机推荐
- kettle学习笔记(七)——kettle流程步骤与应用步骤
一.概述 流程主要用来控制数据流程与数据流向 应用则是提供一些工具类 二.流程步骤 1.ETL元数据注入 类似Java中的反射,在设计时不知道文件名.文件位置等,在真正执行时才知道具体的一些配置等信息 ...
- 20155204《网络对抗》Exp 6 信息搜集与漏洞扫描
20155204<网络对抗>Exp 6 信息搜集与漏洞扫描 一.实验后回答问题 1.哪些组织负责DNS,IP的管理. 互联网名称与数字地址分配机构,简称ICANN机构,决定了域名和IP地址 ...
- AT24C02跨页写数据
AT24C02 EEPROM的写数据分为:字节写数据模式和页写数据模式:字节写就是一个地址一个数据的写,页写是连续写数据,一个地址多个数据的写,但是页写不能自动跨页,如果超出一页长度,超出的数据会覆盖 ...
- JavaScript 变量提升
变量提升(Hoisting):在ES6之前,函数声明和变量声明总是被JavaScript解释器隐式地提升(hoist)到包含他们的作用域的最顶端. 注意: 1. JavaScript 仅提升声明,而不 ...
- Asp.Net_序列化、反序列化
.net序列化及反序列化 在我们深入探讨C#序列化和反序列化之前我们先要明白什么是序列化,它又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.序列化就是把一个对象保存到一个文件或数据库 ...
- MFC学习笔记(一): 不用MFC向导如何新建一个MFC程序
使用Visual Studio新建一个空项目,项目命名为HelloMFC,完成后,打开项目属性页面,将配置属性选项卡中的常规项打开,将其中的MFC的使用属性栏改为:在静态库中使用MFC或者在共享DLL ...
- 总结com组件问题,随笔记录
一.从 IClassFactory 为 CLSID 为 {00024500-0000-0000-C000-000000000046} 的 COM 组件创建实例失败,原因是出现以下错误:80010001 ...
- [转]申瓯 JSY2000-06 程控电话交换机呼叫转移设置
说明:若申瓯程控电话交换机分机有事不在位置上或遇忙分机正忙时为使某些重要来话不丢失,可设置将呼入本机的电话转移至其他分机及公网固定电话或手机.电话交换机使用了本功能不管分机用户在什么地方都能接听到办公 ...
- PAT甲题题解-1096. Consecutive Factors(20)-(枚举)
题意:一个正整数n可以分解成一系列因子的乘积,其中会存在连续的因子相乘,如630=3*5*6*7,5*6*7即为连续的因子.给定n,让你求最大的连续因子个数,并且输出其中最小的连续序列. 比如一个数可 ...
- linux内核分析第五周学习笔记
linux内核分析第五周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...