因为是基础题所以都不算难,个人把碰见过的感觉比较好的练手基础题在这里做个汇总,方便查阅。
枚举
- 一般都是数据量比较小的简单题,难点在于对数据的判断处理。用循环直接对数据区间枚举随后进行判断即可。如果数据量较大,就优化判断条件或者找共性减少运算时间。
1.安全区
题目描述
在一个nn的网格图上有m个探测器,第i个探测器位于(xi,yi)位置,探测半径为ri。
求出nn个点中有多少个是安全的点,即未被探测的点。
输入
第一行为两个整数n,m(1<=n<=100,1<=m<=n*n)
接下来m行每行3个整数表示xi,yi,ri(1<=xi,yi,ri<=n)
输出
输出一个整数表示答案
样例输入
5 2
3 3 1
4 2 1
样例输出
17
OJ链接
思路: 重点是半径判断,我是用sqrt((x-x1) * (x-x1) + (y-y1) * (y-y1)) > r 来判断是否在检测半径内,同时用二维数组来储存是否能被探测到。
AC代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include<bits/stdc++.h> using namespace std;
bool mymap[101][101];
void func(int x,int y,int r,int n) { for(int a=x-r;a<=x+r;a++) { if(a<1||a>n) continue; for(int b=y-r;b<=y+r;b++) { if(b<1||b>n) continue; if(sqrt((x-a)*(x-a)+(y-b)*(y-b))>r) continue; if(!mymap[a][b]) mymap[a][b]=true; } } }
int main() { memset(mymap,false,sizeof(mymap)); int n,m,xi,yi,ri,ans=0; cin>>n>>m;
for(int temp=0;temp<m;temp++) { cin>>xi>>yi>>ri; func(xi,yi,ri,n); } for(int a=1;a<=n;a++) { for(int b=1;b<=n;b++) { if(mymap[a][b]==false) ans++; } } cout<<ans; return 0; }
|
2.统计方形
题目描述
有一个n*m方格的棋盘,求其方格包含多少正方形、长方形(此处长方形不包含正方形)
输入
输入存在多组测试数据。每组测试数据输入两个整数n,m,数字不超过5000
输出
对于每组数据输出一行包含两个整数,分别表示正方形数目和长方形数目
样例输入
2 3
样例输出
8 10
思路: 就是两层循环,代表当前图形的长和宽,长宽一样就是正方形,不一样就是长方形。然后求出这一行能有多少个这种图形(1+(m-b)),再求这一列有多少种这种图形(1+(n-a)),两者相乘就是这个图里有多少种这种图形。然后加到总数里,等循环跑完就是答案。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<bits/stdc++.h> using namespace std;
int main() { int n,m; long long ans1=0,ans2=0; cin>>n>>m; for(int a=1;a<=n;a++) { for(int b=1;b<=m;b++) { if(a==b) { ans1+=(1+(n-a))*(1+(m-a)); } else { ans2+=(1+(n-a))*(1+(m-b)); } } } cout<<ans1<<" "<<ans2; return 0; }
|
- 但是这样复杂度会比较高,可能会超时,所以有第二种求法。先求出总的矩形个数,再用一层循环求出正方形个数,总的减去正方形的就是长方形的。
AC代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <bits/stdc++.h> using namespace std; int main () {
int n,m; while(scanf("%d %d",&n,&m)!=EOF) { long long sum1=0; for(int i=1;i<=min(n,m);i++) { sum1+=(n-i+1)*(m-i+1); } printf("%lld ",sum1); long long sum2=1LL*n*(n+1)/2*1LL*m*(m+1)/2; printf("%lld\n",sum2-sum1); } return 0; }
|
3.连续自然数和(尺取法)
题目
对于给定自然数N,求出存在多少个连续自然数段,长度至少为2,使得这些连续的自然数段之和为N。
输入
输入有若干行,每行一个正整数n。(1<=n<=2000000)
输出
对于每组测试数据输出第一个数字表示答案
样例输入
9
10000
样例输出
2
4
思路: 可以用for循环暴力循环出来,但是我下面是用的尺取法,来减少复杂度。
AC代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include<bits/stdc++.h> using namespace std;
int main() { int n; while(scanf("%d",&n)!=EOF) { int ans=0,temp=0,f=1,e=1; while(n!=0) { while(temp<n&&e<n) { temp+=e; e++; } if(temp<n) { break; } if(temp==n&&e-f>=1) { ans++; } temp-=f; f++; } printf("%d\n",ans); } return 0; }
|
4.蓝桥杯 数字分组
问题描述
输入任意10个浮点数,根据它们的聚集程度划分为3组,输出每一组的平均值。
提供老师上课讲的一种思路:将10个数字进行在数轴上排序,然后计算每两个点间的距离,在所有的距离中选取两个最大距离处断开,这样就把10个数字分为了3组。
本题难度较大,如果深入讨论会比较复杂,大家可以只考虑如下面样例所示的分组情况非常简单的情况,只要简单情况能够成功计算,本题就能得分。
另外,本题内容有些超前,推荐大家自学一下数组那一章中第一节一维数组,然后使用一维数组来做。排序算法可以参考trustie平台上传的冒泡排序法参考资料。
输入格式
十个待输入的浮点数,使用空格隔开
输出格式
三组数的平均数,每输出一个需要换行
样例输入
一个满足题目要求的输入范例。
例1:
50.4 51.3 52.3 9.5 10.4 11.6 19.1 20.8 21.9 49.6
例2:
8.6 7.4 3.5 17.9 19.1 18.5 37.6 40.4 38.5 40.0
样例输出
与上面的样例输入对应的输出。
例1:
10.5
20.6
50.9
例2:
6.5
18.5
39.125
思路: 直接循环枚举检测间隔即可。
AC代码: OJ链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include<bits/stdc++.h> using namespace std;
double shuzu[10]; int main() { double max1=0,max2=0,m1,m2; for(int a=0;a<10;a++) { scanf("%lf",&shuzu[a]); } sort(shuzu,shuzu+10); for(int a=0;a<9;a++) { double temp=shuzu[a+1]-shuzu[a]; if(temp>max1) { max2=max1; m2=m1; max1=temp; m1=a; } else if(temp>max2) { max2=temp; m2=a; } } double temp=0; for(int a=0;a<=min(m1,m2);a++) { temp+=shuzu[a]; } printf("%g\n",temp/(min(m1,m2)+1)); temp=0; for(int a=min(m1,m2)+1;a<=max(m1,m2);a++) { temp+=shuzu[a]; } printf("%g\n",temp/(max(m1,m2)-min(m1,m2))); temp=0; for(int a=max(m1,m2)+1;a<=9;a++) { temp+=shuzu[a]; } printf("%g\n",temp/(9-max(m1,m2))); return 0; }
|