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大的)

    #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行,打码不容易,题解费精力。希望各位走之前留下一个大大的喜欢!(弱弱的说一句还有代码)

猜你喜欢

转载自www.cnblogs.com/yanzifanqiejiang/p/10869594.html