一、选择题
1、B,基础题,考察二进制运算
2、B,基础题,48+9=57
3、C,基础题,考察存储空间计算,8GB/2MB=8*1024/2=4096
4、C,基础题,计算机基础常识,摩尔定律
5、B,根据题意,7个顶点任选2个都恰好有一条边,则就是7选2的组合数,21
6、D,基础题,考察计算机硬件系统,CPU组成,寄存器
7、C,数据结构题,二叉树结点数计算,深度最少的时候必然是完全二叉树,深度为n的满二叉树叶子结点为
2
n
−
1
2^{n-1}
2n−1,2011最接近2048,即
2
11
2^{11}
211,所以n-1=11,n=12
8、B,算法题,考察插入排序的基本思路
9、C,基础题,考察进制转换,二进制转十六进制,每4位二进制转成1位16进制,100/4=25
10、C,基础题,考察计算机文件删除操作常识
11、B,数据结构题,考察BFS和队列的应用
12、A,算法题,考察空间复杂度概念
13、C,数据结构题,链表不能随机访问,只能顺序遍历一遍
14、C,基础题,信息学基础,主流技术应用常识,ABD都是有生物特征,C没有
15、C,数据结构题,考察哈夫曼树,根据哈夫曼算法,构建好哈夫曼树可得C
16、D,基础题,考察编程语言,汇编语言,汇编语言大量应用于较底层的开发应用,没有被淘汰
17、A,算法题,考察回溯算法的基本概念
18、A,基础题,计算机历史常识
19、A,数据结构题,考察图的连通性,依次枚举每个选项即可,寻找每个边是否有其他路径可以替代,只有a边是有可替代的路径
20、C,基础题,考察计算机历史,冯诺依曼的计算机体系结构核心内容,采用存储程序和程序控制原理
二、问题求解
1、数学题,所有的序列里,1的个数要么是偶数,要么是奇数,所以各占一半,所以是8的全排列除以2,128个
2、编辑距离可以用动态规划算法来做,但是本题给出的序列比较简单,可以直接观察得到,1,删除A得到BCDEFG
2、C替换为A得到BADEFG
3、F替换为C得到BADECG
总共3步
三、阅读程序
1、
#include<iostream>
using namespace std;
int main()
{
int i,n,m,ans;
cin>>n>>m;
i=n;
ans=0;
while(i<=m){
ans+=i;
i++;
}
cout<<ans<<endl;
return 0;
}
输入:10 20
简单编程题,考察while循环语句,代码的功能是计算从10累加到20的和,结果是165
2、
#include<iostream>
#include<string>
using namespace std;
int main()
{
string map= "2223334445556667778889999";
string tel;
int i;
cin>>tel;
for(i=0;i<tel.length();i++)
if((tel[i]>='0') && (tel[i]<='9') )
cout<<tel[i];
else if( (tel[i]>='A') && (tel[i]<='Z'))
cout<<map[tel[i]-'A'];
cout<<endl;
return 0;
}
输入:CCF-NOIP-2011
简单编程题,考察字符串遍历和处理,结果为:22366472011
3、
#include<iostream>
#include<cstring>
using namespace std;
const int SIZE = 100;
int main()
{
int n,i,sum,x,a[SIZE];
cin>>n;
memset(a,0,sizeof(a));
for(i=1;i<=n;i++){
cin>>x;
a[x]++;
}
i=0;
sum=0;
while(sum<(n/2+1)){
i++;
sum+=a[i];
}
cout<<i<<endl;
return 0;
}
输入:
11
4 5 6 6 4 3 3 2 3 2 1
编程题,打表可得输出i为3
4、
#include<iostream>
using namespace std;
int solve(int n,int m)
{
int i,sum;
if(m==1) return 1;
sum=0;
for(i=1;i<n;i++)
sum+= solve(i,m-1);
return sum;
}
int main()
{
int n,m;
cin>>n>>m;
cout<<solve(n,m)<<endl;
return 0;
}
输入:7 4
递归求解题,阅读solve函数的递归逻辑,可得m=1时,返回1,否则solve(n,m)的值等于solve(1,m-1)+solve(2,m-1)+…+solve(n-1,m-1),如果打表可得结果20
四、完善程序
1、(子矩阵)给输入一个n1m1的矩阵a,和n2m2的矩阵b,问a中是否存在子矩阵和b相等。若存在,输出所有子矩阵左上角的坐标:若不存在输出“There is no answer”。
#include<iostream>
using namespace std;
const int SIZE = 50;
int n1,m1,n2,m2,a[SIZE][SIZE],b[SIZE][SIZE];
int main()
{
int i,j,k1,k2;
bool good ,haveAns;
cin>>n1>>m1;
for(i=1;i<=n1;i++)
for(j=1;j<=m1;j++)
cin>>a[i][j];
cin>>n2>>m2;
for(i=1;i<=n2;i++)
for(j=1;j<=m2;j++)
[ ① ];
haveAns=false;
for(i=1;i<=n1-n2+1;i++)
for(j=1;j<= [ ② ];j++){
[ ③ ];
for(k1=1;k1<=n2;k1++)
for(k2=1;k2<=[ ④ ] ;k2++){
if(a[i+k1-1][j+k2-1]!=b[k1][k2])
good=false;
}
if(good){
cout<<i<<' '<<j<<endl;
[ ⑤ ];
}
}
if(!haveAns)
cout<<"There is no answer"<<endl;
return 0;
}
若a当中存在与b相等的子矩阵,则如图所示,a中的与b相等的子矩阵的左上角坐标只能在绿色矩阵区域内移动,所以遍历该区域内的每一个坐标,判断以其为左上角坐标的尺寸与b相等的子矩阵是否与b相等。
①cin>>b[i][j]
②m1-m2+1,绿色区域的宽度
③good=true,设置good初值
④m2,比较子矩阵的每一个元素是否与b对应的元素相等
⑤hasAns=true,找到一个子矩阵与b相等
2、(大整数开方) 输入一个正整数n(1≤n≤10^100),试用二分法计算它的平方根的整数部分。
#include<iostream>
#include<string>
using namespace std;
const int SIZE=200;
struct hugeint{
int len,num[SIZE];
};
//其中len表示大整数的位数;num[1]表示个位,num[2]表示十位,以此类推
hugeint times(hugeint a,hugeint b)
// 计算大整数a和b的乘积
{
int i,j;
hugeint ans;
memset(ans.num,0,sizeof(ans.num));
for(i=1;i<=a.len;i++)
for(j=1;j<=b.len;j++)
[ ① ] +=a.num[i]*b.num[j];
for(i=1;i<=a.len+b.len;i++){
ans.num[i+1]+=ans.num[i]/10;
[ ② ];
}
if(ans.num[a.len+b.len]>0)
ans.len=a.len+b.len;
else
ans.len=a.len+b.len-1;
return ans;
}
hugeint add(hugeint a,hugeint b)
//计算大整数a和b 的和
{
int i;
hugeint ans;
memset(ans.num,0,sizeof(ans.num));
if(a.len>b.len)
ans.len=a.len;
else
ans.len=b.len;
for(i=1;i<=ans.len;i++){
ans.num[i]+= [ ③ ] ;
ans.num[i+1]+= ans.num[i]/10;
ans.num[i]%=10;
}
if(ans.num[ans.len+1]>0)
ans.len++;
return ans;
}
hugeint average(hugeint a,hugeint b)
//计算大整数a和b的平均数的整数部分
{
int i;
hugeint ans;
ans=add(a,b);
for(i=ans.len;i>=2;i--){
ans.num[i-1]+=([ ④ ])*10;
ans.num[i]/=2;
}
ans.num[1]/=2;
if(ans.num[ans.len]==0)
ans.len--;
return ans;
}
hugeint plustwo(hugeint a)
// 计算大整数a加2之后的结果
{
int i;
hugeint ans;
ans=a;
ans.num[1]+=2;
i=1;
while( (i<=ans.len)&&(ans.num[i]>=10) ){
ans.num[i+1]+=ans.num[i]/10;
ans.num[i]%=10;
i++;
}
if(ans.num[ans.len+1]>0)
[ ⑤ ];
return ans;
}
bool over(hugeint a,hugeint b)
// 若大整数a>b则返回true,否则返回false
{
int i;
if([ ⑥ ])
return false;
if( a.len>b.len )
return true;
for(i=a.len;i>=1;i--){
if(a.num[i]<b.num[i])
return false;
if(a.num[i]>b.num[i])
return true;
}
return false;
}
int main()
{
string s;
int i;
hugeint target,left,middle,right;
cin>>s;
memset(target.num,0,sizeof(target.num));
target.len=s.length();
for(i=1;i<=target.len;i++)
target.num[i]=s[target.len-i]-[ ⑦ ];
memset(left.num,0,sizeof(left.num));
left.len=1;
left.num[1]=1;
right=target;
do{
middle=average(left,right);
if(over([ ⑧ ]))
right=middle;
else
left=middle;
}while(!over(plustwo(left),right) );
for(i=left.len;i>=1;i--)
cout<<left.num[i];
return 0;
}
高精度运算的应用,代码较长,函数较多,阅读后发现都是高精度运算常用的函数,比如乘法,加法等。
① ans.num[i+j-1],高精度乘法结果数组的下标
② ans.num[i]%=10,低位向高位进位,低位取余数
高精度加法,按位相加
③ a.num[i]+b.num[i]
高精度除以低精度,这里是除以常数2
④ ans.num[i]%2
高精度加低精度
⑤ ans.len++,最高位产生了新的进位,总长度加1
比较两个高精度数的大小
⑥ a.len<b.len, 先比较长度,如果长度小,值必然更小
⑦ '0’或48,将输入的字符串格式的数转换为高精度的字符数组存储方式,注意是逆序
然后使用二分法来逼近求解开方,每次取中点值,判断middle的平方是否大于原数,若大于,则表示取大了,需要在左边继续找,否则要在右边继续找
⑧ times(middle, middle), target
本题代码非常长,但难度其实更小,除了main函数里的7,8两个空,前面都是高精度运算的基本操作,答案都可以在对应的函数代码里找到现成的答案。