2018年3月3日普及组试题题解
(这是我们学校取的名字,由于我不知道题目的来源,就只好按学校取的名字来作为标题了)
我在洛谷上写的博客https://www.luogu.org/blog/chaojixiaozhou/
由于我在洛谷上叫超级小周,所以文章内容的作者名也是超级小周,请不要见怪
2019年3月30日,超级小周迎来了他人生中第一次考试——【NOIP2019普及级别模拟】
由于超级小周这人十分热心老师要求,所以他就发题解啦!
(新人第一次发题解有错误请指出~代码没用freopen)
【NOIP2018普及级别模拟】数池塘
【NOIP2018普及级别模拟】接苹果
【NOIP2018普及级别模拟】找数
【NOIP2018普及级别模拟】最短路线
【NOIP2018普及级别模拟】生成树
【NOIP2018普及级别模拟】数池塘
题目描述
农夫约翰的农场可以表示成 N*M(1<=N<=100,1<=M<=100)个方格组成的矩形。由于近日的降雨,在约翰农场上的不同地方形成了池塘。每一个方格或者有积水('W')或者没有积水('.')。农夫约翰打算数出他的农场上共形成了多少池塘。一个池塘是一系列相连的有积水的方格,每一个方格周围的八个方格都被认为是与这个方格相连的。
现给出约翰农场的图样,要求输出农场上的池塘数。
输入
第 1 行:由空格隔开的两个整数:N 和 M
第 2..N+1 行:每行 M 个字符代表约翰农场的一排方格的状态。每个字符或者是'W'或者是'.',字符之间没有空格。
输出
第 1 行:约翰农场上的池塘数
样例输入
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
样例输出
3
超级小周的思路:哼哼,这道题一看就是深搜或广搜看我分分钟秒掉这道题。
#include<bits/stdc++.h>
using namespace std;
int a,b,ans;
bool zkl[101][101];
void dfs(int x,int y)
{
if (x<1||y<1||x>a||y>b) return;
if (zkl[x][y]==0) return;
zkl[x][y]=0;
dfs(x-1,y-1);
dfs(x+1,y+1);
dfs(x-1,y+1);
dfs(x+1,y-1);
dfs(x+1,y);
dfs(x,y+1);
dfs(x-1,y);
dfs(x,y-1);
}
int main()
{
cin>>a>>b;
char c;
for (int i=1;i<=a;i++)
for (int j=1;j<=b;j++)
{
cin>>c;
if (c=='W') zkl[i][j]=1;
}
for (int i=1;i<=a;i++)
for (int j=1;j<=b;j++)
if (zkl[i][j]==1)
{
ans++; dfs(i,j); //相当于一个扩散过程
}
cout<<ans;
//hahaha想不到吧
}
其实这是我考完后才做出来的T T,考试时深搜忘了,没想到还可以这样做...考试时我写的代码很暴力,就不打上来糊弄了。(说出来你可能不信我还骗了60分)
这题超级小周完败,那就下一题吧。
【NOIP2018普及级别模拟】接苹果
题目描述
很少有人知道奶牛爱吃苹果。农夫约翰的农场上有两棵苹果树(编号为 1 和 2),每一棵树上都长满了苹果。奶牛贝茜无法摘下树上的苹果,所以她只能等待苹果从树上落下。但是,由于苹果掉到地上会摔烂,贝茜必须在半空中接住苹果(没有人爱吃摔烂的苹果)。贝茜吃东西很快,所以她接到苹果后仅用几秒钟就能吃完。 每一分钟,两棵苹果树其中的一棵会掉落一个苹果。贝茜已经过了足够的训练,只要站在树下就一定能接住这棵树上掉落的苹果。同时,贝茜能够在两棵树之间快速移动(移 动时间远少于 1 分钟),因此当苹果掉落时,她必定站在两棵树其中的一棵下面。此外,奶牛不愿意不停地往返于两棵树之间,因此会错过一些苹果。 苹果每分钟掉落一个,共T(1<=T<=1000)分钟贝茜最多愿意移动W(1<=W<=30)次。现给出每分钟掉落苹果的树的编号,要求判定贝茜能够接住的最多苹果数。开始时贝茜 在 1 号树下。
输入 第 1 行:由空格隔开的两个整数:T 和 W 第 2..T+1 行:1 或 2(每分钟掉落苹果的树的编号)
输出 第一行:在贝茜移动次数不超过 W 的前提下她能接到的最多苹果数
样例输入 7 2
2
1
1
2
2
1
1
样例输出
6
超级小周的思路:啊啊啊啊!!!!nm这什么题...短暂的思考后
。。。
奶牛喜欢吃苹果?我怎么不知道。(想歪了)
这题显然是动规做,计算每种情况的值,用一个max()函数求最大值。数据比较小,可以不用特殊处理。
#include<bits/stdc++.h>
using namespace std;
int dp[10000][10000]={0},a[1001];
int main(){
int k,m;
cin>>k>>m;
for(int i=1;i<=k;i++){
cin>>a[i];
a[i]--;//我来记录树的编号
}
for(int i=1;i<=k;i++)
for(int j=0;j<=m;j++){
if(!j)dp[i][j]=dp[i-1][j]; //我来保存值
else dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]);//我来求最大值
if(j%2==a[i])dp[i][j]++;//我来判断是否能接到
}
int ans=0;
for(int i=1;i<=m;i++)ans=max(ans,dp[k][i]);//我来完成答案
cout<<ans;
return 0;}
Zzz舒服,那就下一道。
【NOIP2018普及级别模拟】找数
题目描述
给定一个长度为N的正整数序列, 以及另一个数K (1<=K<=N), 然后要你找到序列中第K大的数(关于第 K 大的数:例如序列{1,2,3,4,5,6}中第 3 大的数是 4)。 输入
输入文件 find.in,输入两行,第一行两个数 N、K,N表示序列的长度,K表示要找在这个序列 中的第K大的数。 第二行,N个数,用空格隔开。 输出
输出文件 find.out,输出序列中的第K大的数。
样例输入
6 3
5 2 4 3 1 6
样例输出
4
超级小周的思路:这道题用sort轻松搞定,但有个陷阱就是去不去重,这题老师说不去重,那就不去重吧(例如:4 3 3 2 1,其实2是第3大的)
考试前老师没说去不去重,我考试的时候没想到去重,竟然误打误撞的AC了!(开心的拍起了肚皮)
#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[3000001];
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);//我懒得写自定义函数...
cout<<a[n-k+1];
return 0;}
下一道。
【NOIP2018普及级别模拟】最短路线
题目描述 某城市的街道是一个很规整的矩形网格,有 M 条南北向的纵街,N 条东 西向的横街。现要从西南角的 A 走到东北角的 B,最短的走法共有多少种?
输入 输入文件 Sline.in,一行,两个数 M,N,其中 2<M,N<=800;
输出 输出文件 sline.out,输出最短路的走法总数.
样例输入
7 5
样例输出
210
超级小周的思路:这题显然是让我找规律,我在电脑上画了一下图,发现有如此规律。
a[n][m]=a[m][n];
a[n][m]=a[n-1][m]+a[n][m-1];
规律都出来了,还怕写不出来吗?
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long a[10000][10000];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
a[i][1]=1;
}
for(int j=1;j<=m;j++){
a[1][j]=1;
}
a[2][2]=2;
int nn=2,mm=2,t=0;
for(int nn=2;nn<=800;nn++){
for(int mm=2;mm<=800;mm++){
a[nn][mm]=a[nn-1][mm]+a[nn][mm-1];
}
}
cout<<a[n][m];
return 0;}
考完才发现数据范围超出long long限制,那就需要高精度和字符压缩了。本人菜,写不出来。求dalao写出来放在评论区,谢谢!还有因为a[n][m]=a[m][n]此代码可以优化一下,由于我懒这里交给观众来优化吧~~~~
【NOIP2018普及级别模拟】生成树
题目描述 给出一个结点数为 N 的无向完全图,即任意结点两两相连,且每条边长为1。LLJ想知道这个图的生成树个数。但这个数量太大了,LLJ 会懒得看,所以他只想看这个数量模 K 后的结果(若 K=0,输出-1即可) 注:生成树定义:在图中节点数为 N,边数为 N-1 的连通子图。
输入
输入共一行,两个非负整数 N K;
输出
输出共一行一个整数,即方案数模 K 后的结果。
样例输入
样例输入①
1 10
样例输入②
4 13
样例输入③
100 23
样例输出
样例输出①
1
样例输出②
3
样例输出③
3
超级小周的思路:这题也是找规律。n个结点数的图生成树的个数为n^(n-2)个,所以可以用快速幂来做。
#include<bits/stdc++.h>
using namespace std;
long long n,m,sum=1;
long long kuai(long long x,long long y){
while(y){
if(y&1)sum=sum*x%n;
x=x*x%n;
y>>=1;
}
return sum;
}
int main(){
cin>>m>>n;
if(m==1)cout<<"1";
else if(n==0)cout<<"-1";
else if(m==0)cout<<"0";
else cout<<kuai(m%n,m-2);
return 0;}
好啦,代码打完了希望不会有下一次,如果你没看到我的问题就请跳到267行,打码不容易,题解费精力。希望各位走之前留下一个大大的喜欢!(弱弱的说一句还有代码)