DAY 1        2019.4.28


例题1

题解:

例题2

题解:

例题3

题解:

vis[ ]判断是否为素数,pri[ ]储存素数

例题4

题解:

例题5

题解:

PS: i  <  1<<n        i<2^n

(1<<j)& i      如果2^j最后一位和 i 相同,返回1

例题6

判回文数是N√N,素数NlogN

枚举:

1.从起点开始向四个方向扩展

2.到一个点卡死,删除栈中的位置,回到前一步继续搜

3.找到一种解

4.这也是一个解

PS:DFS不会死循环,走完一个方向就会走其他方向

例题:

题解:

实际上就是寻找是否存在路径小于等于T

VIS[ ][ ]判断这个坐标是否走过

PS:

1.DFS使用一遍之后清空所影响数据

2.命名变量不要重名

  每组数据开始之前ans要回归初始值

[代码]:

#include<cstdio>
#include<algorithm> #define N 15 using namespace std; int i,j,m,n,p,k,vis[N][N],tmp,T,ans=,tot; char c[N][N]; pair<int,int> Ans[N*N]; const int X[]={,,-,};
const int Y[]={-,,,}; int check(int x,int y) //是否合法
{
if (x<=||y<=||x>n||y>n) return ;
if (vis[x][y]) return ;
if (c[x][y]=='#') return ;
return ;
} void dfs(int x,int y)
{
if (c[x][y]=='E')
{
ans=min(ans,tot);
return;
}
vis[x][y]=;
Ans[++tot]=make_pair(x,y);
int i; //辅助变量,开在里面
for (i=;i<;++i)
if (check(x+X[i],y+Y[i]))
dfs(x+X[i],y+Y[i]);
--tot;
vis[x][y]=;
} void Main()
{
ans=(int)1e9;
scanf("%d%d",&n,&T);
for (i=;i<=n;++i) scanf("%s",c[i]+);
for (i=;i<=n;++i)
for (j=;j<=n;++j)
if (c[i][j]=='S') dfs(i,j);
printf(ans<=T?"YES\n":"NO\n");
} int main()
{
int T;
scanf("%d",&T);
for (;T--;) Main(); //用一个过程实现多组数据,模块化
}

1.沿四个方向扩展

2.起点出发,四周搜,可以走,加队列

3.维护每个点距离起点的最短距离

[代码]:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<bitset>
#include<vector> #define ls (t<<1)
#define rs ((t<<1)|1) #define N 15
#define M 200005
#define K 17 #define pb push_back
#define fi first
#define se second
#define mk make_pair using namespace std; int i,j,n,m,Time; char c[N][N]; int vis[N][N]; pair<int,int> Q[N*N]; const int x[]={-,,,};
const int y[]={,,-,}; int check(int x,int y)
{
if (x<||y<||x>n||y>n) return ;
if (c[x][y]=='#') return ;
if (vis[x][y]!=-) return ;
return ;
} int bfs(int sx,int sy)
{
int i,l,r;
memset(vis,-,sizeof(vis));
Q[r=]=mk(sx,sy); vis[sx][sy]=;
for (l=;l<=r;++l)
{
int ax=Q[l].fi,ay=Q[l].se;
if (c[ax][ay]=='E')
{
if (vis[ax][ay]<=Time) return ;
return ;
}
for (i=;i<;++i)
if (check(ax+x[i],ay+y[i]))
{
Q[++r]=mk(ax+x[i],ay+y[i]);
vis[ax+x[i]][ay+y[i]]=vis[ax][ay]+;
}
}
return ;
} int main()
{
int T; scanf("%d",&T);
for (;T--;)
{
scanf("%d%d",&n,&Time);
for (i=;i<=n;++i) scanf("%s",c[i]+);
for (i=;i<=n;++i)
for (j=;j<=n;++j) if (c[i][j]=='S') {
if (bfs(i,j)) puts("YES"); else puts("NO");
}
}
}

DFS  先扩展,不行就回头

    存储空间小

BFS  一般是求最短路径

    全部走,所有路径集合,空间大

    为所有可能的结果开数据

Pair 数组相当于一个结构体,int int两个元素,存横纵坐标

Vector

Vector可以用来存图存数据

可以自己定义类型

相当于开了N个int数组,长度可以很长

其实相当于开了一个二维数组

相当于在数组第y行最后加入一个x

在数组第x行最后加入一个y

每一行数组表示该点可以到达的点(也就是这两个点之间联通)

弹出

[代码]:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<bitset>
#include<vector> #define ls (t<<1)
#define rs ((t<<1)|1) #define N 100005
#define M 200005
#define K 17 #define pb push_back
#define fi first
#define se second
#define mk make_pair using namespace std; vector<int>v[N]; int i,j,m,n,p,k,vis[N],Q[N],ans; void bfs(int x)
{
int l,r;
Q[r=]=x;
vis[x]=;
for (l=;l<=r;++l)
{
int p=Q[l];
for (i=;i<(int)v[p].size();++i) //遍历所有出边
{
int k=v[p][i]; //vector类型其实相当于二维数组
if (vis[k]) continue;
vis[k]=;
Q[++r]=k;
}
}
} int main()
{
scanf("%d%d",&n,&m);
for (i=;i<=m;++i)
{
int x,y;
scanf("%d%d",&x,&y);
v[y].push_back(x);
v[x].push_back(y);
}
for (i=;i<=n;++i)
if (!vis[i])
{
bfs(i);
ans++;
} cout<<ans; }

PS:

k=奇数  =>  k^=1为k=k-1

k=偶数  =>  k^=1为k=k+1

[代码]:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<bitset>
#include<vector> #define ls (t<<1)
#define rs ((t<<1)|1) #define N 1005
#define M 200005
#define K 17 #define pb push_back
#define fi first
#define se second
#define mk make_pair using namespace std; int i,j,m,n,p,k,r[]; int vis[N][N]; pair<int,int> Q[][N*N]; char c[N][N]; const int X[]={-,,,};
const int Y[]={,,-,}; int check(int x,int y)
{
if (x<=||y<=||x>n||y>m) return ;
if (vis[x][y]) return ;
return ;
} void bfs(int x,int y)
{
int i,l,now=;
Q[][r[]=]=make_pair(x,y);
memset(vis,-,sizeof(vis));
vis[x][y]=;
for (;;) //死循环
{
now^=;
if (!r[now]) return;
for (l=;l<=r[now];++l)
{
int ax=Q[now][r[now]].first,ay=Q[now][r[now]].second;
for (i=;i<;++i)
if (check(ax+X[i],ay+Y[i]))
{
int ck=c[ax+X[i]][ay+Y[i]]=='#';
if (!ck) //如果可以走,加入当前队列
{
vis[ax+X[i]][ay+Y[i]]=vis[ax][ay];
Q[now][++r[now]]=make_pair(ax+X[i],ay+Y[i]);
}
else // 否则加入暂时先不扩展的队列
{
vis[ax+X[i]][ay+Y[i]]=vis[ax][ay]+;
Q[now^][++r[now^]]=make_pair(ax+X[i],ay+Y[i]);
}
} // 维护两个不同的队列
}
}
} int main()
{
scanf("%d%d",&n,&m);
for (i=;i<=n;++i) scanf("%s",c[i]+);
for (i=;i<=n;++i)
for (j=;j<=m;++j)
if (c[i][j]=='S') bfs(i,j);
for (i=;i<=n;++i)
for (j=;j<=m;++j)
if (c[i][j]=='E') printf("%d\n",vis[i][j]);
}

能BFS就BFS,否则考虑DFS

K表示有没有用过正方形

Id表示高度,不可以超边界

代码加了剪枝

一个固体块,确定一个小块的位置,其余小块的位置就可以确定,整个固体块也就确定了

比如,( a, b ) 第一块固体块的左上角方块坐标

( c , d ) 第二块固体块的左上角方块坐标

( e , f ) 第三块固体块的左上角方块坐标

然后根据相对位置推出其余小块的坐标

六维

比如,( 0 , 0 ) 第一块固体块的左上角方块坐标

( c , d ) 第二块固体块的左上角方块坐标

( e , f ) 第三块固体块的左上角方块坐标

然后根据相对位置推出其余小块的坐标

移动的话要根据相对位置

状态数404

一个四维状态


化简一下

ans=∑(Ai – Bi)*j+Bi*n- Ai

Ai – Bi越小越靠后

∑Bi(ti-T)=0

我们会得到一半正的一半负的

正:∑Bi,ti-T

负:∑Bi,ti-T

若|正|<|负|

那么正的就全取,负的有一部分为之抵消,至于未能抵消掉的,就直接不开此水龙头

[代码]:

#include<cstdio>
#include<algorithm>
#include<cstring> #define N 300005 using namespace std; int a[N],t[N],i,j,m,n,p,k,id[N],ID[N],sum[N],T; double ans; int cmp(int x,int y)
{
return sum[x]<sum[y];
} int main()
{
scanf("%d%d",&n,&T);
for (i=;i<=n;++i)
{
scanf("%d",&a[i]);
}
for (i=;i<=n;++i) scanf("%d",&t[i]);
for (i=;i<=n;++i)
{
if (t[i]==T) ans+=a[i];
else if (t[i]<T) id[++id[]]=i,sum[i]=T-t[i];
else ID[++ID[]]=i,sum[i]=t[i]-T;
}
sort(id+,id+id[]+,cmp);
sort(ID+,ID+ID[]+,cmp);
long long suma=,sumb=;
for (i=;i<=id[];++i)
suma+=1ll*sum[id[i]]*a[id[i]];
for (i=;i<=ID[];++i)
sumb+=1ll*sum[ID[i]]*a[ID[i]];
if (suma<sumb)
{
swap(suma,sumb);
for (i=;i<=n;++i) swap(ID[i],id[i]);
}
for (i=;i<=ID[];++i) ans+=a[ID[i]];
for (i=;i<=id[];++i)
if (1ll*sum[id[i]]*a[id[i]]>=sumb)
{
ans+=.*sumb/sum[id[i]];
break;
}
else
{
ans+=a[id[i]];
sumb-=1ll*sum[id[i]]*a[id[i]];
}
printf("%.10lf\n",ans);
}


示例:

【代码】:

#include<bits/stdc++.h>

using namespace std;

int a[],n,m,l,r,mid,x;

int main()
{
scanf("%d%d",&n,&x); for(int i=;i<=n;++i)
scanf("%d",&a[i]); sort(a+,a+n+); //保证递增 int l=,r=n+,mid=; //初始化 while((l+r)>>!=mid) //如果还可以继续二分
{
mid=(l+r)>>;
if(x>=a[mid]) l=mid;
else r=mid;
} cout<<l;
//找到x在序列中排第几
}

预处理相邻距离

距离最远的那次尽可能短

使用mid的跳跃是否合法

【代码】:

#iclude<bits/stdc++.h> 

#define N 300005

using namespace std;

int i,j,m,n,p,k,a[N],x;

int check(int x)
{
int i,cnt=;
for (i=;i<=n;++i) if (a[i]-a[i-]>x) return ; //跳不过去
for (i=;i<n;)
{
for (j=i;j<=n&&a[j]-a[i]<=x;++j);
++cnt;
i=j-;
}
if (cnt<=m) return ;
return ;
} int main()
{
scanf("%d%d",&n,&m);
for (i=;i<=n;++i) scanf("%d",&a[i]);
sort(a+,a+n+);
int l=,r=(int)1e9,mid=; //因为没有给定右端点
while ((l+r)>>!=mid)
{
mid=(l+r)>>;
if (check(mid)) r=mid;
else l=mid;
}
printf("%d\n",r);
}

P2678 跳石头

这也是个二分题,好像和刚才的不大一样

所以应该是:

#include<cstdio>
#include<algorithm>
#include<cstring> #define N 300005 using namespace std; int a[N],t[N],i,j,m,n,p,k,id[N],ID[N],sum[N],T; double ans; int cmp(int x,int y)
{
return sum[x]<sum[y];
} int main()
{
scanf("%d%d",&n,&T);
for (i=;i<=n;++i)
scanf("%d",&a[i]); for (i=;i<=n;++i) scanf("%d",&t[i]);
for (i=;i<=n;++i)
{
if (t[i]==T) ans+=a[i];
else if (t[i]<T) id[++id[]]=i,sum[i]=T-t[i];
else ID[++ID[]]=i,sum[i]=t[i]-T;
}
sort(id+,id+id[]+,cmp);
sort(ID+,ID+ID[]+,cmp);
long long suma=,sumb=;
for (i=;i<=id[];++i)
suma+=1ll*sum[id[i]]*a[id[i]];
for (i=;i<=ID[];++i)
sumb+=1ll*sum[ID[i]]*a[ID[i]];
if (suma<sumb)
{
swap(suma,sumb);
for (i=;i<=n;++i) swap(ID[i],id[i]);
}
for (i=;i<=ID[];++i) ans+=a[ID[i]];
for (i=;i<=id[];++i)
if (1ll*sum[id[i]]*a[id[i]]>=sumb)
{
ans+=.*sumb/sum[id[i]];
break;
}
else
{
ans+=a[id[i]];
sumb-=1ll*sum[id[i]]*a[id[i]];
}
printf("%.10lf\n",ans);
}

【代码】

#include<bits/stdc++.h> 

#define N 500005

using namespace std;

int i,j,m,n,p,k,a[N],ty,x;

long long b[N];   //表示前K个数的前缀和 

double check(int x)   //平均数
{
return .*(b[x-]+a[n])/x;
} int main()
{
scanf("%d",&m);
for (;m--;)
{
scanf("%d",&ty); //操作名称 if (ty==) //插入数的操作
{
scanf("%d",&x);
a[++n]=x;
b[n]=b[n-]+x;
} else
{
int l=,r=n;
while (r-l>) //保留一个尽量大的小三分区间,比如只有10个数
{
int len=(r-l+)/,mid1=l+len,mid2=mid1+len; //三分,每次缩小三分之一
if (check(mid1)<check(mid2)) r=mid2; //因为函数图像是倒着的
else l=mid1;
} //在区间内部枚举一下
double ans=;
for (i=l;i<=r;++i) ans=max(ans,a[n]-check(i));
printf("%.10lf\n",ans);
} }
}

五一培训 DAY1的更多相关文章

  1. 五一培训 清北学堂 DAY1

    今天是冯哲老师的讲授~ 1.枚举 枚举也称作穷举,指的是从问题所有可能的解的集合中一一枚举各元素. 用题目中给定的检验条件判定哪些是无用的,哪些是有用的.能使命题成立的即为其解. 例一一棵苹果树上有n ...

  2. 纪中2018暑假培训day1提高b组改题记录

    收到意见,认为每天的程序和随笔放在一起写的博客太长了,于是分开整理 day1 模拟赛,看了看提高a组t1的样例就不太想写,于是转而写b组 t1: Description 给定一个n个点m条边的有向图, ...

  3. 中山纪念中学培训DAY1

    哇啊啊啊啊啊啊$……$ 并不像说环境怎么样. $Day1$模拟赛 稳重一点选了提高$B$ 然后$5min$后: $t1$装压$DP$最短路 $t2$裸地贪心 $t3……$哇$t3$怎么做啊啊啊啊. $ ...

  4. 五一培训 清北学堂 DAY4

    今天上午是钟皓曦老师的讲授,下午是吴耀轩老师出的题给我们NOIP模拟考了一下下(悲催暴零) 今天的内容——数论 话说我们可能真的是交了冤枉钱了,和上次清明培训的时候的课件及内容一样(哭. 整除性 质数 ...

  5. 常州培训 day1 解题报告

    第一题:(骗分容易,AC难.) 题目大意: 给出一个字符串,找出满足条件A的区间的个数.A:字符A,B,C的出现次数相同. 都出现0次也算,区间的长度可以是0(就是只有一个数).30% |S| ≤ 1 ...

  6. 五一培训 清北学堂 DAY2

    今天还是冯哲老师的讲授~~ 今日内容:简单数据结构(没看出来简单qaq) 1.搜索二叉树 前置技能 一道入门题在初学OI的时候,总会遇到这么一道题.给出N次操作,每次加入一个数,或者询问当前所有数的最 ...

  7. 五一培训 清北学堂 DAY3

    今天是钟皓曦老师的讲授~ 今天的内容:动态规划 1.动态规划 动态规划很难总结出一套规律 例子:斐波那契数列  0,1,1,2,3,5,8,…… F[0]=0 F[1]=1 F[[n]=f[n-1]+ ...

  8. 泉五培训Day1

    T1 树学 题目 [问题描述] 给定一颗 n 个点的树,树边带权,试求一个排列 P,最大化下式 其中,calc(a, b)表示树上由a到b经过的最大边权. [输入格式] 第一行一个整数 n,表示点数下 ...

  9. 性能测试培训day1

    测试本质: 1构造测试数据和期望结果 2执行 3验证 自动化测试: 写完代码,单元测试测代码逻辑,单元测试搞清楚代码逻辑就行了(白盒测试)先静态,运行前用工具扫描BUG例如(a==11写成a=11), ...

随机推荐

  1. react_app 项目开发 (8)_角色管理_用户管理----权限管理 ---- shouldComponentUpdate

    角色管理 性能优化(前端面试) 需求:只要执行 setState(), 就会调用 render  重新渲染.由于有时调用了 setState,但是并没有发生状态的改变,以致于不必要的刷新 解决: 重写 ...

  2. 什么是Hash?Hash有哪些特性?

    Hash 把任意长度的输入通过散列算法变换成固定长度的输出 Hash的特性: 输入域无穷,输出域有限.例如:有无穷多个(在工程中可以具体到多少个,例如1000)输入参数经过hash函数映射后得到有限的 ...

  3. Android 进程间的通信

    localsocket:   https://blog.csdn.net/azhengye/article/details/73863404 https://www.cnblogs.com/basta ...

  4. Python全栈-magedu-2018-笔记8

    第四章 - IPython 使用 帮助 ? Ipython的概述和简介 help(name) 查询指定名称的帮助,是python帮助 obj? 列出obj对象的详细信息 obj?? 列出更加详细的信息 ...

  5. in与exists和not in 与 not exists的区别

    1.in 与 exists: 外表大,用IN:内表大,用EXISTS: 原理: 用in:外表使用了索引,直接作hash连接: 用exists:内表使用了索引,外表作loop循环再进行匹配: 2.not ...

  6. JAVA RPC (五) 之thrift序列化RPC消息体

    让大家久等了.继续更新thrift序列化的消息体,下面我们一步一步的看一看thrift的rpc是怎么实例化消息体的. 首先我们先准备一个request文件 namespace java bky str ...

  7. Head First Python-Python简单处理文件

    前面介绍了自定义格式化输出列表函数printList(),下面再介绍下格式化列表项及列表项的排序. 这里有一组列表数据,记录运动员跑步时间的,要求按照时间大小进行排序.这里每项数据记录的时间格式不一样 ...

  8. 关于Android布局优化的代码使用

    1.  include标签: include标签的作用是在一个布局文件中导入另一个布局文件.在开发中经常会有多个页面同时拥有一部分相同的布局,这个时候如果每个布局都把那个部分的代码写一遍就会使得代码重 ...

  9. SharePoint使用jsom查询当前用户信息

    前置环境:sharepoint 'use strict'; var context = SP.ClientContext.get_current(); var user = context.get_w ...

  10. 神贴真开眼界:为什么很多人倡导重视能力和素质,但同时对学历有严格要求?——代表了上一场比赛的输赢,招聘成本很重要。如果上一场游戏失败了,尽量让自己成为当前群体的尖子。学历只是其中的一个作品而已,但学历代表了学生时代为之做出的牺牲。人群自有偏向集中性 good

    对于软件工程师职位,没学历没关系,如果真觉得自己才高八斗,请在简历里附上 github项目链接或者 appstore/google play上你的作品.如果学历比别人低,那么想必是把时间和精力用在了其 ...