NOIP2017提高组模拟赛4 (总结)
NOIP2017提高组模拟赛4 (总结)##
第一题 约数
设K是一个正整数,设X是K的约数,且X不等于1也不等于K.
加了X后,K的值就变大了,你可以重复上面的步骤。例如K= 4,我们可以用上面的规则产生所有的非素数. 可以通过5次变化得到。
24: 4->6->8->12->18->24.
现在给你两个整数N 和 M, 求最少需要多少次变化才能到从 N 变到 M. 如果没法从N变到M,输出-1.
这道题就是很简单的bfs,可以观察到n变化到m是近似成倍增长的。其实从最小到最大的变化也就只有30次而已。
#include<cstdio>
#include<algorithm>
#include<cmath>
typedef long long ll;
using namespace std;
const int maxl=100;
const int oo=1e9;
const int N=100000;
int T,n,m;
int op[N+10],ct,ch,f[N+10];
bool uss[N+10];
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=N;i++) f[i]=oo,uss[i]=0;
f[n]=0; ct=ch=1; op[ct]=n;
while(ch<=ct)
{
if(op[ch]<m && f[op[ch]]<maxl)
{
int i=floor(sqrt(op[ch]));
i=(m<op[ch]+i)?m-op[ch]:i;
for(;i>=2;i--)
{
if(op[ch]%i==0)
{
if(op[ch]+i<=m && f[op[ch]]+1<f[op[ch]+i])
{
if(!uss[op[ch]+i]) op[++ct]=op[ch]+i,uss[op[ch]+i]=1;
f[op[ch]+i]=f[op[ch]]+1;
//printf("%d %d -> %d %d\n",op[ch],f[op[ch]],op[ch]+i,f[op[ch]+i]);
}
if(i*i!=op[ct])
{
int yu=op[ch]+op[ch]/i;
if(yu<=m && f[op[ch]]+1<f[yu])
{
if(!uss[yu]) op[++ct]=yu,uss[yu]=1;
f[yu]=f[op[ch]]+1;
//printf("%d %d -> %d %d\n",op[ch],f[op[ch]],yu,f[yu]);
}
}
}
}
}
uss[op[ch]]=0;
ch++;
}
printf("%d\n",(f[m]!=oo)?f[m]:-1);
}
return 0;
}
第二题 警察与小偷
为帮助捕获在逃的犯人, 警局引进了一套新计算机系统. 系统覆盖了N 个城市,有E条双向的道路。城市标号为1 到N. 犯人经常从一个城市逃到另外一个城市. 所以警察想知道应该在哪里设置障碍去抓犯人.计算机系统需要回答下面两种类型的问题:
1. 考虑城市A 、B; 如果把连接城市G1和G2的那条公路切断,逃犯还能从城市A逃到城市B吗?
2. 考虑三个城市A、B 、C. 如果把城市C封锁(则不能从其他进入城市C),逃犯还能从城市A逃到城市B吗?
你的任务是帮计算机系统回答这些提问。(一开始,任意两个城市都是可以相互到达的).
这是一道好题,数据很大,但边是双向的,只是删一条边或一个点,而且保证了点两两之间是连通的。(这些很重要)
那么,可以从dfs序入手,dfs序是一棵树,其中会有返祖边。(如图)
那我们只需要判断删掉的点或边是否在u到v的路径上,不在的话,删了也没用。(用三次lca处理)。
如果删的是边,判断边的左右端点是否为一个块,(dfn[a]>dfn[b] 且 low[a]≤dfn[b])是的话,删了还是u,v保持连通的,否则u,v不连通,(必经路被删)
如果删的是点c。lca---u,v的公共祖先
若c在u->lca的路径上,则更新uminlow(能到达的最早的点)。
若c在v->lca的路径上,则更新vminlow(能到达的最早的点)。
判断uminlow和vminlow都小于c就保证了u,v之间连通。
否则不连通。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
typedef long long ll;
using namespace std;
const int mm=500100;
const int nn=100100;
int N,E,Q,dt,TN;
bool vis[nn];
int ti[nn],low[nn];
int ne[mm<<1],to[mm<<1],h[nn],tt;
int f[nn][20];
void addedge(int a,int b)
{
to[++tt]=b; ne[tt]=h[a]; h[a]=tt;
to[++tt]=a; ne[tt]=h[b]; h[b]=tt;
}
void dfs(int x,int fa)
{
f[x][0]=fa;
ti[x]=low[x]=++dt; vis[x]=1;
for(int p=h[x];p;p=ne[p])
{
int u=to[p];
if(u==fa) continue;
if(!vis[u]) dfs(u,x);
low[x]=imin(low[x],low[u]);
}
}
int lca(int a,int b)
{
if(a==b) return a;
if(ti[a]<ti[b]) swap(a,b);
for(int i=TN;i>=0;i--)
if(ti[f[a][i]]>ti[b]) a=f[a][i];
return (f[a][0]);
}
int mingo(int a,int b)
{
for(int i=TN;i>=0;i--)
if(ti[f[a][i]]>ti[b]) a=f[a][i];
return a;
}
bool judge(int u,int v,int a)
{
int w=lca(u,v);
int x=lca(u,a);
int y=lca(v,a);
if(x!=a) swap(x,y);
return (x==a && y==w);
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&N,&E); tt=1;
for(int i=1;i<=E;i++)
{
int A,B; scanf("%d %d",&A,&B);
addedge(A,B);
}
ti[0]=low[0]=0; dt=0; dfs(1,0);
f[1][0]=1; TN=0;
for(int i=1;(1<<(i-1))<N;i++)
{
TN++;
for(int j=1;j<=N;j++)
f[j][i]=f[f[j][i-1]][i-1];
}
scanf("%d",&Q);
for(int i=1;i<=Q;i++)
{
int ww,a,b,c,d;
scanf("%d",&ww);
if(ww==1)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
if(ti[a]<ti[b]) swap(a,b);
if(ti[c]<ti[d]) swap(c,d);
if(judge(a,b,c) && judge(a,b,d))
{
if(low[c]<=ti[d]) printf("yes\n"); else printf("no\n");
} else printf("yes\n");
} else
if(ww==2)
{
scanf("%d%d%d",&a,&b,&c);
if(ti[a]<ti[b]) swap(a,b);
if(judge(a,b,c))
{
if(lca(a,b)==c)
{
int xx=mingo(a,c),yy=mingo(b,c);
if(low[xx]<ti[c] && low[yy]<ti[c]) printf("yes\n"); else printf("no\n");
} else
{
int dp=0;
if(lca(a,c)==c) dp=a; else dp=b;
int xx=mingo(dp,c);
if(low[xx]<ti[c]) printf("yes\n"); else printf("no\n");
}
} else printf("yes\n");
}
}
return 0;
}
第三题 圆桌会议
有N个人顺时针围在一圆桌上开会,他们对身高很敏感. 因此决定想使得任意相邻的两人的身高差距最大值最小. 如果答案不唯一,输出字典序最小的排列,指的是身高的排列.
一道贪心的题目。
假设不是一个环,而是一条链,那该怎么做?
很显然,低-高-低这类是不可能的,因为低-低-高肯定比它更优。
是环的话,最低-最高这肯定是不行的,因为需要最大的最小。
可以考虑数列拆成两部分(排序后按A5-A3-A1-A2-A4-A6这样排)。
这样是最优的,详细证明如下:
A5-A3-A1-A2-A4-A6,假设A4-A6最大,可以改得更优,A5移过来,变成A3-A1-A2-A4-A5-A6,那么A3-A6比A4-A6跟大,答案肯定不会优。
其他情况也差不多。
Ai和Ai+1之间肯定改不了(-_-|| 显然的)。
字典序怎么办?先求出minans,然后放A1,在右侧放A2,判断A4和当前头的距离是否合法(小于等于minans),不合法的话A3只能放在头的左侧作为新的头(不合法的话,再将A3放在右侧的话,A4就没法放了 放左或放右都会使最大距离大于minans),合法的话就将A3放在右侧,以此类推。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define imax(a,b) ((a>b)?(a):(b))
typedef long long ll;
using namespace std;
bool cmp(int a,int b) { return (a<b); }
int ng,n,d[60],ans,p[60];
int ya[60],yb[60],l1,l2;
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d",&ng);
while(ng--)
{
scanf("%d",&n); ans=0;
for(int i=1;i<=n;i++) scanf("%d",&d[i]);
sort(d+1,d+1+n);
int w=(n+1)>>1,q=1,cc=w;
p[w]=d[1];
for(int i=2;i<=n;i++)
{
if((i&1)==0) w+=q; else w-=q;
p[w]=d[i];
q++;
}
ans=abs(p[1]-p[n]);
for(int i=2;i<=n;i++) ans=imax(ans,abs(p[i]-p[i-1]));
l1=1; l2=1;
ya[1]=d[1]; yb[1]=d[1];
for(int i=2;i<=n;i++)
{
if(abs(d[i+1]-yb[l2])>ans) yb[++l2]=d[i]; else ya[++l1]=d[i];
}
for(int i=1;i<=l1;i++) printf("%d ",ya[i]);
for(int i=l2;i>=2;i--) printf("%d ",yb[i]); printf("\n");
}
return 0;
}
考的不怎么好,没状态,最后一题想出来但字典序问题没搞好。争取在每一次考试中都能不断进步吧!
超越自己,让自己变得更好 ------------加油,努力
NOIP2017提高组模拟赛4 (总结)的更多相关文章
- NOIP2017提高组 模拟赛15(总结)
NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...
- NOIP2017提高组 模拟赛13(总结)
NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...
- NOIP2017提高组模拟赛 10 (总结)
NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...
- NOIP2017提高组模拟赛 8(总结)
NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...
- NOIP2017提高组模拟赛 9 (总结)
NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...
- NOIP2017提高组模拟赛 7(总结)
NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...
- NOIP2017提高组模拟赛5 (总结)
NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...
- 计蒜客NOIP2017提高组模拟赛(三)day1
火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A1,A2,⋯,An点生命值,一次火山喷发总计 MM 轮 ...
- 计蒜客NOIP2017提高组模拟赛(四)day1
T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...
随机推荐
- 使用rsync同步数据(by quqi99)
作者:张华 发表于:2015-12-28版权声明:能够随意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) 急需使 ...
- 疯狂Java学习笔记(72)-----------大话程序猿面试
大话程序猿面试 10个我最喜欢问程序猿的面试问题 程序猿面试不全然指南 10个经典的C语言面试基础算法及代码 程序猿的10大成功面试技巧 程序猿选择公司的8个标准 编程开发 8个值得关注的PHP安全函 ...
- golang sftp传输文件
之前有一篇介绍如何使用 golang 通过SSH协议来执行远程命令:golang执行远程命令 同样,通过SSH协议也可以使用 golang 来远程传输文件. 除了 SSH 的库,为了传输文件,还需要用 ...
- 开发工具 | 利用 deployd 搭建个人博客
前端er,通过利用deployd + mongodb,实现可视化的接口编写,自定义mock数据,数据存储在mongodb中:deployd目前还没有中文网,更多信息请参考http://deployd. ...
- Oracle数据库基础(二)
1.表名命名规则:必须以字母开头,不能超过30个字符,不要有Oracle保留字 2.数据类型 字符型: char :2000个字符 定长 效率高 ...
- Linux学习日记——源码编译Apache
[本文为笔者在学习Linux 下的软件安装时,尝试使用源码安装Apache 的过程,事后进行一个小小的总结,发现错误望指正.] 一.典型的源码编译安装软件的过程包括以下3步: 1) 运行 config ...
- (转载)Android项目实战(二十七):数据交互(信息编辑)填写总结
Android项目实战(二十七):数据交互(信息编辑)填写总结 前言: 项目中必定用到的数据填写需求.比如修改用户名的文字编辑对话框,修改生日的日期选择对话框等等.现总结一下,方便以后使用. 注: ...
- Navicat for Mysql 关于1130错误,无法正常方法解决的解决办法。
本人因为失误操作,不小心将mysql 玩崩了.导致一直报1130错误,无法进入. 看了很多网上的帖子,但是那些办法都行不通.最后通过好友的指点,解决了这个问题. 1.停止MySQL服务,执行net ...
- X位的有/无符号整数
目录 X位的有符号整数 X位的无符号整数 知识点来自leetcode整数翻转 X位的有符号整数 以4位为例,不管多少位都是相同的概念 在有符号整数中,第一位二进制位用来表示符号,0为正,1为负 最大值 ...
- criteria的projection做分页