NOIP(第20届)--2014--普及组--复赛--试题与答案(NA20)

2022-07-07 已有0人阅读 作者: IT航班

中小学编程红宝书.zip

关键词:

北京中关村;海淀黄庄;北京大学;清华大学。少儿编程;中小学编程;信息学竞赛;计算机竞赛;NOIP;NOIP竞赛;CSP-J/S竞赛;NOI竞赛。北京中学;东坝。

      2014年、普及组、复赛,第20届。

面向6-18岁中小学生,做最专业的中小学编程教育。


解析与答案:


1题:珠心算测验

1、说明

A、试题类型:

       算法问题。

 

B、算法模型:

       算法与排序的结合。

 

C、试题说明:

       无。

 

2、代码

#include <stdio.h>

#include <stdlib.h>

 

int main()

{

    int i, j, k, n, b, m;

    int a[100];

    scanf("%d", &n);    //输入数据个数

      

    for(i=0; i<n; i++)  //循环输入正整数值

    {

        scanf("%d", &a[i]);

    }

      

    b = 0;

      

    for(i=0; i<n-1; i++)   //循环把数组中整数排序,冒泡排序

    {

        for(j=i+1; j<n; j++)

        {

            if(a[i] > a[j])

            {

                b = a[i];

                a[i] = a[j];

                a[j] = b;

            }

        }

    }

    m = 0;

       /*a[i]中数据以排序,故两个数之和等于a[i]的两个数必在第i个数a[i]之前

       把a[i]第二个数之前的数据逐个相加直到符合条件*/

   

    for(i=2; i<n; i++)  //一层循环,从第2个数据开始遍历a[i]

    {

        for(j=0; j<i-1; j++)    //二层循环,控制j从第0个数据开始到i-1遍历a[i]

        {

            for(k=j+1; k<i; k++)    //三层循环,从k=j+1开始遍历到i

            {

                if(a[j]+a[k] == a[i])   //比较如果i前有两个不同数据之和等于a[i]则m+1

                {

                    m++;

                    goto skip;  //如果有一个符合条件的就用goto跳出多重循环,不用再比较其余的啦

                }

            }

        }

skip: ;

    }

    printf("%d\n", m);

    return 0;

}

2题:比例简化

1、说明

A、试题类型:

       经典数学问题。

 

B、算法模型:

       比例简化。

 

C、试题说明:

       无。

 

2、代码

#include<bits/stdc++.h>

using namespace std;

#define N 105

long long a[N];

 

int gcd(int x, int y)

{//最大公约数

       if(y == 0)

              return x;

       return gcd(y, x%y);

}

 

int main()

{

       int A, B, x, y, L, tmp, a, b, ans, flag = 1;

       cin >> A >> B >> L;

      

       int yueshu = gcd(A, B);

       tmp = max(A, B);

      

       A = A/yueshu;B = B/yueshu;

      

       for(int i=1; i<=L; i++)

       {

              flag = 1;

              for(int j=1; j<=L && flag; j++)

                     if(gcd(i, j) == 1)

                     {//确保两数为质数

                            if(i * B - j * A >= 0)

                            {//方程求解

                                   ans = i * B - j * A;

                                   if(ans < tmp)//最佳解

                                          tmp = ans, a = i, b = j;

                            }

                            else

                                   flag = 0;

                     }

       }

       cout << a << " " << b;

       return 0;

}

3题:螺旋矩阵

1、说明

A、试题类型:

       数学问题。

 

B、算法模型:

       比例简化。

 

C、试题说明:

第一种思路是开一个二维数组,螺旋填入数字,按照坐标输出对应位置的元素。

当n非常大的时候,无法开出相应的二维数组。然后就想到模拟螺旋填数过程,用两个变量x,y存当前填数的格子的坐标。当x=i,y=j的时候,输出当前要填的数。

 

如果一个格子一个格子的去填数字一定会超时,而且在一条直线上直到转弯前需要填的格子数目是可以通过计算得出的。只要在转弯处判断目标格子是否在当前要填的直线段上。

 

在的话就用已经填的格子数目加上目标格子相应坐标与当前直线段的端点坐标的差,否则加上当前直线段所有要填的格子数目,然后转弯。

2、代码

#include <iostream>

#include <cstdlib>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

 

int main()

{

    int n;

    scanf("%d",&n);

 

    int x,y;

    scanf("%d%d",&x,&y);

 

    int xx=1,yy=1;

    long long int ans = 1;

    int a=n,b=n,c=1,d=1;//相当于划定边界

 

    if(n%2==1&&(n+1)/2==x&&(n+1)/2==y)//特判n为奇数且求中心格子

        ans=n*n;

    else

       {

        while(1)

              {

            if(xx==x&&y>=yy&&y<a)

                     {

                ans+=(y-yy);

                break;

            }

                     else

                     {

                ans+=(a-yy);

                yy=a;

            }

            a--;

            if(yy==y&&x>=xx&&x<b)

                     {

                ans+=(x-xx);

                break;

            }

                     else

                     {

                ans+=(b-xx);

                xx=b;

            }

            b--;

            if(xx==x&&y<=yy&&y>c)

                     {

                ans+=(yy-y);

                break;

            }

                     else

                     {

                ans+=(yy-c);

                yy=c;

            }

            c++;

            if(yy==y&&x<=xx&&x>d)

                     {

                ans+=(xx-x);

                break;

            }

                     else

                     {

                ans+=(xx-d);

                xx=d+1;

                yy=c;

            }

            d++;

        }

    }

    printf("%lld\n",ans);

    return 0;

}

4题:子矩阵

1、说明

A、试题类型:

       基本逻辑。

 

B、算法模型:

       枚举与排序。

 

C、试题说明:

直接枚举行和列的话,复杂度C(16/2,16)^2无法承受。

 

如果只枚举行的话,是可以承受的。

 

枚举行之后,对于列dp就很简单了。预处理之后复杂度可以做到O(m^3)。

2、代码

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

 

const int oo=0x3f3f3f3f;

bool use[20];

int a[20][20],dp[20][20],self[20],dif[20][20],n,m,r,c,ans=oo;

 

void solve()

{

    int i,j,k,last;

    for (i=1;i<=m;i++)

    {

        last=-1;

        self[i]=0;

        for (j=1;j<=n;j++)

        {

            if (!use[j]) continue;

            if (last!=-1) self[i]+=abs(a[j][i]-last);

            last=a[j][i];

        }

    }

      

    for (i=1;i<=m;i++)

              for (j=i+1;j<=m;j++)

              {

                     dif[i][j]=0;

                    

                     for (k=1;k<=n;k++)

                     {

                            if (!use[k]) continue;

                            dif[i][j]+=abs(a[k][i]-a[k][j]);

                     }

              }

              memset(dp,0x3f,sizeof(dp));

              dp[0][0]=0;

             

              for (i=1;i<=m;i++)

                     for (j=1;j<=c&&j<=i;j++)

                            for (k=0;k<i;k++)

                                   dp[i][j]=min(dp[i][j],dp[k][j-1]+self[i]+dif[k][i]);

                            for (i=c;i<=m;i++)

                                   ans=min(ans,dp[i][c]);

}

 

void DFS(int p,int now)

{

    if (p==n+1)

    {

        solve();

        return;

    }

      

    if (n-p+now>=r)

              DFS(p+1,now);

      

    if (now+1<=r)

    {

        use[p]=1;

        DFS(p+1,now+1);

        use[p]=0;

    }

}

 

int main()

{

    int i,j;

    scanf("%d%d%d%d",&n,&m,&r,&c);

      

    for (i=1;i<=n;i++)

              for (j=1;j<=m;j++)

                     scanf("%d",&a[i][j]);

             

              DFS(1,0);

              printf("%d\n",ans);

}

 

IT航班提供:课程视频、、课程书籍、竞赛辅导、少儿编程指导、课程采购、加盟、少儿编程资料、少儿编程课程、保送生、特长生、加分、中小学计算机教育、中小学信息学、竞赛、中小学信息学课程、人工智能、中小学编程加盟、少儿编程加盟、品牌加盟、技术加盟、技术指导、课程加盟、师资培训、中小学编程教辅资料、中小学编程教师培训、少儿编程教学书籍、少儿编程视频、教学书籍、教师培训、教学视频、CSP-J/S、中小学信息学课程服务、竞赛指导、课程提供、国内外计算机中小学计算机竞赛、信息学竞赛、信息学课程提供商、信息学奥林匹克。

      

IT航班支持----中小学编程比赛汇总:

 

第一部分:国内比赛(IT航班支持)   

1、软件能力认证(CSP-JS) 

2、全国青少年信息学奥林匹克联赛(NOIP)    

3、全国青少年信息学奥林匹克竞赛(NOI)

4、中国青少年………………………  

5、………………………创新挑战赛  

6、全国青少年………………………  

7、………………………

8、 恩欧希教育信息化发明创新奖  

9、世界机器人大赛(WRC) 

10、………………………大赛    

11、少………………………智能教育成果展示大赛 

12、“明天小小科学家”奖励活动

13、………………………    

14、………………………    

15、国际信息学……………………… 

16、………………………    

 

第二部分:国际比赛(IT航班支持)   

17、………………………    

18、国际………………………    

19、………………………

20、美国信息学……………………… 

21、加拿大……………………… 

22、官方邀请赛 (CCO)     

23、国际计算思维………………………    

24、美国计算机……………………… 

25、澳大利亚………………………    

 

第三部分:企业比赛(IT航班支持)   

26、微软MTA    

27、………………………挑战赛 

28、………………………科学奖 

29、………………………学奖    

30、………………………创新挑战赛 

31、………………………挑战赛 

32、………………………芯计算机表演赛 

33、………………………大赛    

 

第四部分:Scratch相关竞赛(IT航班支持)    

34、全国中小学生电脑制作大赛     

35、………………………    

36、………………………    

37、………………………    

 

第五部分:其它(IT航班支持)   

38、NOI夏令营  

39、NOI冬令营(NOIWC)  

40、全国青少年……………………… 

41、国际青少年………………………

 

 

联系方式:

A、官方网址:

http://www.itflight.net


B、微信公众号:

添加微信,获取资料。

image.png

 



关注公众号,获取动态。

image.png