2013年蜀山区青少年信息学竞赛
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2013年蜀山区青少年信息学竞赛
小学组试题
一、题目概况
二、注意事项
1.考试时间为150分钟。
2.务必看清题目,严格按照所要求的格式输入、输出。
3.在调试程序时请先使用题目中的示例数据,然后再自行设计多组测试数据进行调试。
4.每题一般有10个测试点,测试有严格的时间限制,请尽可能优化
算法。
5.命名规则:
(1)每题都规定了该题的英文名称。
(2)程序文件和数据文件的主文件名都是该题的英文名字。
(3)程序文件扩展名采用语言环境的默认扩展名。
(4)数据文件都是文本文件,输入和输出文件的扩展名分别是.in
和.out。
6.程序应从输入文件读取数据,并严格地按照规定的输出格式将结
果输出到输出文件中。
输入数据文件和输出数据文件都与程序在同一个目录中,由于程序所在目录是不确定的,因此不允许在文件名中含有盘符信息和任何形式的路径信息。
7.选手应在指定分区的根目录下建立以准考证号命名的文件夹,并将所完成各题的源程序文件和可执行文件拷贝到该文件夹中。
第一题数字求和
(sum.pas/c/cpp)
【问题描述】
给定一个正整数a,以及另外的n个正整数,要求:这n个整数中,小于a的整数的和是多少?
【输入数据】
输入数据有两行,第一行两个正整数a和n,含义如上所述;
第二行包含n个小于1000的正整数,两个正整数之间以空格隔开。
【输出数据】
输出一行,给出一个正整数,表示n个数中小于a的数的和。
【样例输入】
10 5
1 2 3 4 11
【样例输出】
10
【数据范围】
对于50% 的数据,n<=5;
对于100%的数据,n<=1000, a<=2000000000
第二题数字统计
(tongji.pas/c/cpp)
【问题描述】
某次科研调查时得到了n个自然数,每个数均不超过1500000000
(1.5*109)。
已知不相同的数不超过10000个,现在需要统计这
些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
【输入数据】
输入文件包含n+1行;
第一行是整数n,表示自然数的个数;
第2~n+1每行一个自然数。
【输出数据】
输出文件包含m行(m为n个自然数中不相同数的个数),
按照自然数从小到大的顺序输出。
每行输出两个整数,分别
是自然数和该数出现的次数,其间用一个空格隔开。
【样例输入】8 2 4 2 4 5 100 2 100
【样例输出】flag[70]++; i,flag[i]
2 3
4 2
5 1
100 2
int k=1,i=0,x=a[i];
while(a[i]= =x)
{i++;k++; }
cout<<x<<”“<<k<<endl;
【数据范围】
40%的数据满足,1<=n<=1000
80%的数据满足,1<=n<=50000
100%的数据满足,1<=n<=200000,每个数均不超过1500 000 000(1.5*109)for(i=1;i<=10;i++)
for(j=1;j<=100;j++)
cout<<i*j<<endl;
循环不超过1亿(8个0),数组不超过90 0000(90万),改变算法思想《1》如果读的每个数的值都不超过100000,int a[100000];读入x ;
a[x]++;
for(i=1;i<=100000;i++)
if(a[i>0)
out<<i<<”“<<a[i]<<endl;
《2》定义数组是int a[200000],num;
void
<3>DP动态规划:自己+潜力最大的合作伙伴。
***核心是填记忆数组(你要求什么他就表示什么,就是潜力)
#include<fstream>
using namespace std;
ifstream in("tongji.in");
ofstream out("tongji.out");
int a[200000],num,n;
void read()
{
int i,x;
in>>n;
for(i=0;i<n;i++)//下标从0开始,为了用sort函数
in>>a[i];
//排序
sort(a,a+n);//下标从0开始排序
for(i=0;i<n;i++)//测试一下排序结果可对》
out<<a[i]<<" ";
for(i=0;i<n;i++)
{
x=a[i]; //x=1
num=0;//统计相同数的个数
while(a[i]==x)
{
num++;//num=3
i++;//i=3
}
out<<x<<" "<<num<<endl;
i--;//退一位,回到正确位置,否则会跳过下一数
}
}
int main()
{
read();
in.close();
out.close();
}
第三题计数
(count.pas/c/cpp)
【问题描述】
小牛牛正在学习怎么用小木棒数数,他的左右手各拿500根木棒。
当爸爸问她“n (1<=n<=1000)是多少”,小可可的回答就是拿出n个小木棒。
为了让问题简单一些,爸爸告诉他正确的小木棒表示方式:
(1)这个数可以用一只手或两只手中的木棒表示;
(2)如果这个数用两只手中的木棒表示,木棒多的手先给出。
比如爸爸问她“4是多少”,小可可有3种表示方法:
(1)一只手拿出4个小木棒(可以是左手中的木棒也可以是右手中的木棒,只算一种);(2)一只手拿出3个小木棒,另一只手拿出1个小木棒;
(3)一只手拿出2个小木棒,另一只手拿出2个小木棒。
你的任务是,对于爸爸的提问,确认小牛牛有几种正确的回答方法。
【输入数据】
输入文件共一行为一个1到1000之间的整数。
【输出数据】
输出文件共一行为一个整数,表示方法整数。
【样例输入】
4
【样例输出】
3
#include<iostream>
using namespace std;
int n,num=0;
/*
4:4----3
1+3
2+2
5: 5-------3
1+4
2+3
6:0+6 ---4
1+5
2+4
3+3
7:0+7----4
1+6
2+5
3+4
1000==1
500+500
500=251
501=0+501 ***---250
=1+500
=2+499
...
=250+251
502=0+502+1+501***
=2+500
=3+499
...
*/
void read()
{
int t;
cout<<"input n"<<endl;
cin>>n;//n=i+(n-i)
//n=7 i:01..3 n=8 i:01.4
for(int i=0;i<=(n/2);i++)
{
if(n-i<=500)
{
// cout<<i<<"+"<<n-i<<"="<<n<<endl;
num++;
}
else continue;
// fenjie(i,n-i,n);
//fenjie(0,6,6) (1,5,6) (2,4,6),(3,3,6)
}
}
int main()
{
read();
cout<<"num----"<<num;
if(n<=500)
cout<<n/2+1;
else cout<<n/2+1-(n-500);
system("pause");
return 1;
}
第四题过河问题
(river.pas/c/cpp)
【问题描述】
在一个大晴天,牛牛与同学们一共N个人出游,他们走到一条河的东岸边,想要过河到西岸边,二东岸边有一条小船。
船太小了,一次只能乘坐两人。
每个人都有一个渡河时间T,船划到对岸的时间等于船上渡河时间较长的人所用时间。
现在已知N个人的渡河时间T,牛牛想要你告诉他,他们最少要花费多少时间,才能使所有人都过河。
注意,只有船在东岸(西岸)是东岸(西岸)的人才能坐上船划到对岸。
【输入数据】
输入文件第一行为人数N以下有N行,每行一个数。
第i+1行的数为第i个人的渡河时间。
【输出数据】
输出文件仅包含一个数,表示所有人都渡过河的最少渡河时间。
【样例输入】
4
6
7
10
15
【样例输出】
42
【样例解释】
初始:东岸{1,2,3,4},西岸{}
第一次:东岸{3,4},西岸{1,2} 时间7
第二次:东岸{1,3,4},西岸{2} 时间6
第三次:东岸{1},西岸{2,3,4} 时间15
第四次:东岸{1,2,西岸{3,4} 时间7
第五次:东岸{},西岸{1,2,3,4} 时间7
所以总时间为7+6+15+7+7=42,没有比这个更优的方案。
【数据范围】
对于40%的数据,N<=8;
对于100%的数据,N<=100000。
#include<fstream>
using namespace std;
ifstream in("sheng.in");
ofstream out("sheng.out");
int a[1000],n;
int f[1000];//记忆数组
void read()
{
int i;
in>>n;
for(i=0;i<n;i++)//下标从0开始
in>>a[i];//读入原始数组
//第一个填最后一个记忆数组是1
f[n-1]=1;
for(i=n-2;i>=0;i--)//从倒数第二个到第一个依次填记忆数组
{
max1=0 //求最大,如果一个人都不和你合作
for(j=i+1;j<=n-1;j++)//从你后面一个到最后一个求合作与潜力的最大值if((a[i]<a[j])&&(f[j]>max1))//合作看原始数组,潜力看记忆数组
max1=f[j];
f[i]= 1+max1;//自己加在潜力最大的合作伙伴
}
max1=0;//求记忆数组最大
for(i=0;i<n;i++)
if(f[i]>max1)
max1=f[i];
out<<max1<<endl;
}
int main()
{
read();
in.close();
out.close();
}
贪心算法:
DP动态规划:专门用来解决最优化问题,把每个人的潜力挖出来。
你的潜力=自己+潜力最大的合作伙伴。
--------------问题的关键:潜力(记忆)数组的建立。
满足下列两条:
最优化原理(局部最优、整体最优)、
无后效性(当前的状态只与他后面的状态相关,与他前面的已经走过的路无关)。
合肥—》北京——》内蒙古
--》状态转换方程:
为每个数建立记忆(潜力)数组。
f[n]
最长上升子序列 输出:4
n 5
合作:后面的值比前面的值大。
a[i]<a[j]
潜力最大的合作伙伴:
a[1] a[2] a[3] a[4] a[5]
11 34 5 89 167
f[1]=1+3=4 f[2]=1+max1=3 f[3]=3 f[4]=1+max1-1=2 f[5]=1
i=3; f[3]=1+2=3
i=2;max1=0;j=3.4.5 ,j=3,j=4,max1=2;j=5,
i=1;j=2,3,4,5->max1=0;j=2: a[i]<a[j],max1=3 ;j=3,j=4,j=5,
cin>>n;
for( i=1;i<=n;i++)
cin>>a[i];//下标从1开始
f[n]=1;//先填最后一个,因为他后面没有人了,最长上升子序列就是1
for( i=n-1;i>=1;i-- )//从倒数第2个一直填到第1个
{
max1=0;//如果没有人和你合作
for (j=i+1....<=n)合作伙伴的范围
if ((a[i]< a[j])&&(f[j]>max1)) //愿意合作并且要找潜力最大
max1=f[j];//把潜力最大的合作伙伴的值记下来
f[i]=1+max1;//填自己+max1
} //end for i
换:输出删除k个数,得到最长上升子序列n-k
1、最长上升子序列
2、飞翔、锋火传递
3、魔法课,数字塔,传纸条
4、最小伤害,摆花、方格游戏、方格取数、乘积最大数,
5、糖果盒、八皇后、n123,(递归回溯),数的分解6=1+5=2+4=3+3....
6、快速排序、栈、队列、树、huffman树、图,最小生成树、拓扑排序、最短路径、SPFA
7、上楼梯,堆排序、强盗分珍宝
20名,40名,60名(278名)。