赞
踩
目录
就在前两天,我参与了第十三届蓝桥杯省赛(2022年4月17日)C++中级组,考题挺难,但发挥较好。这是一篇相关的题解,题是我在考试时电脑截屏下来的。
1.二进制数1101111转换为十六进制是( )
A、157 B、111 C、6f D、3f
2.下列指针的用法中,不正确的一项是( )
A、int i; int *p=&i;
B、int i; int *p; i=*p;
C、int *p; p=0;
D、int i=5; int *p; p=&i;
3.以下对main()函数描述正确的一项是( )
A、main()函数必须写在所有函数的前面
B、main()函数必须写在所有函数的后面
C、main()函数可以写在任何位置,但不能放到其它函数的里面
D、main()函数必须固定位置
4.下列函数中不能重载的一项是( )
A、构造函数 B、析构函数 C、成员函数 D、非成员函数
5.定义char a; float b; double c; 执行语句 c=a+b+c 后c的变量类型是( )。
A、char B、float C、double D、int
CBCBC
(1) 四位截断, (110)2=(6)16 , (1111)2=(f)16 ,
(2) *p是一个空地址, 无法引用, B选项错误; C选项属于危险语法, 因为地址0是一个未知地址
(3) main()函数可以写在其它函数后面或前面(声明即可), 其它函数也可以调用main()函数,
但main()函数显然无法“放到”其它函数里面, 任何函数都做不到, 文字游戏, 有点无聊。
(4) 析构函数只有一个,无法构成重载。
(5) 已经定义了c是double, 任何运算都不会改变数据的类型, 类型覆盖只会影响运算的结果。
顺便说下类型覆盖, 浮点型>整型>字符型, 布尔型与字符型运算后结果为整型。
给定两个正整数N和M (0<N<200, 0<M<200, N≠M), 比较两个正整数的大小,然后将较大的一个正整数输出。例如:N=145, M=100, 比较后145大于100, 故输出145.
样例输入:
145 100
样例输出:
145
很简单,这里用到了max函数,注意用algorithm头文件。
- #include<iostream>//调用输入输出流头文件
- #include<algorithm>//调用算法头文件
- using namespace std;//使用标准名字空间
- int main(){//主函数开始
- int m,n;//定义整数类型变量m,n
- cin>>m>>n;//输入m,n的值
- cout<<max(m,n);//输出m,n的最大值
- return 0;//主函数结束,返回0
- }
给定一个正整数N,然后将N分解成3个正整数之和,计算出共有多少种符合要求的分解方法.要求:
1) 分解的3个正整数各不相同;
2) 分解的三个正整数中都不含数字3和7.
如:N为8, 可分解为(1,1,6), (1,2,5), (1,3,4), (2,2,4), (2,3,3),
其中满足要求的分解方法有1种,为(1,2,5) .
输入描述:
输入一个正整数N(5<N<501), 表示要分解的正整数
输出描述:
输出一个整数,表示共有多少种符合要求的分解方法.
样例输入:
8
样例输出:
1
把这个题看成两部分:1.将输入的正整数拆分成三个不相同的正整数的和;2.判断这三个整数是否含有数字3或7。
第一部分可通过枚举实现将三个数设为i,j,n-i-j,保证依次增大,则枚举i即可完成枚举。第二部分可通过子函数来判断。
同时,也可以用深度搜索Dfs解决问题。
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- bool n37(int n){//子函数,用来判断参数是否含有数字3或7
- while(n){
- if(n%10==3 or n%10==7) return 1;//如果个位为3或7,返回1
- n/=10;//删除个位
- }
- return 0;//如果各位都没有3或7,返回0
- }
- int main(){//主函数开始
- int n,cnt=0;//定义整数类型变量n,cnt并初始化赋值为0
- cin>>n;//输入n的值
- for(int i=1;i<=n/3-1;i++){//i为三数中最小,至多为n/3-1
- if(n37(i)) continue;//如果i含有3或7,跳出本次循环,枚举下一个i
- for(int j=i+1;j<=n/2;j++){//j为三数中第二小,至多为n/2,保证大于i
- if(n37(j)) continue;//如果j含有3或7,跳出本次循环,枚举下一个j
- if(n37(n-i-j)) continue;//如果n-i-j含有3或7,跳出本次循环,枚举下一个j
- if(n-i-j>j) cnt++;//走到这一步,则三个正整数一定都不含3或7,只需保证n-i-j>j,则拆分符合条件
- }
- }
- cout<<cnt;//输出cnt的值
- return 0;//主函数结束,返回0
- }
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- int cnt;//定义整数类型变量cnt
- bool ex_37(int n){//判断37;
- while(n){
- if(n%10==3 || n%10==7) return 0;//若n包含3或7, 返回 0
- n/=10;//查看下一位
- }
- return 1;//否则返回 1
- }
- void dfs(int n,int k,int a){//将 n拆成 k份, 至少拆 a
- if(k==1){ //已拆完
- if(n>=a) cnt+=ex_37(n);//能拆时,判断n是否含有37
- return;//返回
- }
- for(int i=a;i*k<=n;i++) //继续拆
- if(ex_37(i))//如果没有37
- dfs(n-i,k-1,i+1);//递归
- }
- int main(){//主函数开始
- int n;//定义整数类型变量
- cin>>n;//输入n的值
- dfs(n,3,1);//深搜
- cout<<cnt<<endl;//输出cnt
- return 0;//主函数结束,返回0
- }
提示信息:
因数: 整数a除以整数b, (B≠0)的商正好是整数而没有余数,我们就说b是a的因数。
公因数: 给定若干个整数,如果有一个(些) 数是他们共同的因数,那么这个(些)数就叫做它们的公因数。
互质数: 公因数只有1的两个非零自然数叫做互质数.
例如: 2和3的公因数只有1,为互质数。
某商店将一种糖果, 按照数量打包成N和M两种规格来售卖(N和M维护质数, 且N和M有无数包)这样的售卖方式会限制一些数量的糖果,不能买到。那么在给出N和M的值,请你计算出最多不能买到的糖果数量。
输入描述:
输入两个正整数M, (2<N<M<100, N和M为互质数), 表示这两种规格的糖果数量, 正整数之间用一个空格隔开.
输出描述:
输出一个整数,表示最多不能买到的糖果数量.
样例输入:
2 3
样例输出:
1
法一:这个题其实是数学题,容易证明:如果m,n互质,对于所有大于m×n的数,都可以表示成am+bn的形式,其中a,b均为整数,所以我们要找的数在1~m×n-1之间。(数学中进一步可得该数即为m×n-m-n)。
所以我们可以让i从从m×n-1开始向下枚举,如果i为m的倍数,则该数能表示,然后检查i-1;若不为m的倍数,则减去n,再检查,重复上述过程,直到i小于0,若均不能表示,则i即为我们要找的最大值。法二:由 "Sylvester定理" 可知, 对互质整数对(a,b) :
当 n > ab-a-b 时, ax + by = n 恒有非负整数解;
当 n = ab-a-b 时, ax + by = n 无 非负整数解;
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- int main(){//主函数开始
- int n,m;//定义整数类型变量n,m
- cin>>n>>m;//输入n,m的值
- int i=m*n-1;//i从m*n-1开始向下枚举
- while(1){//装死循环
- int j=i,flag=1;//用j代替i来枚举,因为过程中需要j不停自减,立个flag
- while(j>=0){//当j还为正整数时,继续检查j
- if(j%n==0) {flag=0;break;}//如果j是n的倍数,则一定能表示出来,flag倒下,跳出循环
- j-=m;//如果j不是n的倍数,减掉一个m后继续检查
- }
- if(flag==1) break;//如果flag还在,说明j一直不能被表示,跳出循环
- i--;//如果flag倒了,则说明j能被表示,i--,检查下一个数,继续循环
- }
- cout<<i;//输出i的值
- return 0;
- }
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- int main(){//主函数开始
- int n,m;//定义整数类型变量n,m
- cin>>n>>m;//输入n,m的值
- cout<<n*m-n-m<<endl;//输出n*m-n-m的值并换行
- return 0;//主函数结束,返回0
- }
手工课上, 老师拿出N张长方形彩纸, 且每张彩纸上都画着W*H的网格(网格铺满整张彩纸).现在老师将N张彩纸裁剪出K张大小相同的正方形, 并且要使才剪出的正方形的边长最大(裁剪的正方形边长必须为整数).
例如: N=2, 有2张彩纸,第一张彩纸W=4,H=3, 第二张彩纸W=5,H=4, K=6, 裁剪的6个正方形边长最大是2.
当给出N张长方形彩纸W和H, 及K的值, 请计算出将N张彩纸裁剪出K张大小相同的正方形,正方形的边长最大是多少(裁剪的正方形边长必须为整数).
输入描述:
输入分为N+1行, 第一行为正整数N(1<N<500), 表示彩纸数量;
以下n行每行有两个正整数W和H, 表示每张彩纸的宽和高, 整数之间用一个空格隔开;
最后一行为正整数K(1<K<500), 表示要剪成的正方形数.
输出描述:
输出一个整数,表示正方形的边长最大是多少.
样例输入:
2
4 3
5 4
6样例输出:
2
法一:按照要求,我们要尝试剪出最大的正方形,通过各长方形长÷边长×各边÷边长,得到该正方形能剪出几个,再将这个个数与输入的k进行对比,如果够了,则直接输出此时的边长,如果不够,则边长--,再尝试。最开始的边长可以很大,防止不够用,所以我们直接选择所有长宽中的最大值(这个数是一定不行的,但从这个数开始算算的比较快且不会漏答案)。
法二:"二分答案"
已知正方形个数 k, 求最大边长 a, 比较麻烦;
反之, 若已知边长 a, 求能切出的正方形个数 k, 则较容易。
故不妨尝试所有可能的 a, 看对应的 k能否满足要求。
一个个尝试又有点慢, 可以对答案进行二分查找。
- #include<iostream>//调用输入输出流头文件
- #include<algorithm>//调用算法头文件
- using namespace std;//使用标准名字空间
- int main(){//主函数开始
- int n,k;int a[500],b[500]; //数组a,b分别用来存储长和宽
- cin>>n;//输入n的值
- for(int i=0;i<n;i++)//for循环,计数器i从0自增到n-1,共循环n次
- cin>>a[i]>>b[i];//输入n个长方形的长和宽
- cin>>k;//输入k的值
- int big=max(*max_element(a,a+n),*max_element(b,b+n));//找到所有长宽中的最大值
- while(1){//装死循环
- int sum=0;//sum用来存储所有正方形中能剪出的正方形个数
- for(int i=0;i<n;i++)
- sum+=(a[i]/big)*(b[i]/big);//对于每一个要剪出的正方形,每张纸能剪出的个数即为该算式
- if(sum>=k) break;//如果正方形个数够了,跳出循环
- big--;//big自减1
- }
- cout<<big;//输出此时的边长
- return 0;//主函数结束,返回0
- }
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- int n,k,w[509],h[509];//定义整数类型n,k,w[509],h[509]
- bool check(int a){//判断: 切边长为 a的小正方形能否凑够 k个
- int cnt=0;//定义计数器cnt
- for(int i=0;i<n;++i)//for循环,计数器i从0自增到n-1,共循环n次
- cnt+=(w[i]/a)*(h[i]/a); //就硬切, 然后硬加
- return (cnt>=k); //返回cnt是否大于k
- }
- int main(){//主函数开始
- cin>>n;//输入n的值
- for(int i=0;i<n;++i)//for循环,计数器i从0自增到n-1,共循环n次
- cin>>w[i]>>h[i];//w和 h的顺序其实也无所谓, 摊手
- cin>>k;//输入k的值
- int L=1, R=*max_element(w,w+n)+1;//随便搞个上下限, 无脑二分:
- while(L+1<R){//当L+1小于R
- int mid=(L+R)/2;//往中间猜
- if(check(mid)) L=mid;//猜对-->边长小了-->提高下限
- else R=mid;//猜错-->边长大了-->降低上限
- }
- cout<<L<<endl;//输出L的值
- return 0;//主函数结束,返回0
- }
有一块农田被划分为N*M块, 农作物和杂草分布生长在农田中, 其中农作物使用大写字母“R”表示,杂草使用大写字母“X”表示. 请计算出农田中有几块独立的农作物区域(独立的农作物区域指该区域上下左右都被杂草围住, 且N*M以外的区域都是杂草).
例如: N=4,M=4, 4*4的农田中, 农作物和杂草分布如下图:
这块4*4的农田中有3块独立的农作物区域(红色的三部分).
输入描述:
输入分为n+1行, 第一行为两个正整数n和m (1<n<500, 1<m<500), 表示农田的长和宽, 数字间用一个空格隔开;
以下n行每行有m个大写字母, 表示每格为农作物或杂草.
输出描述:
输出一个整数,表示农田中有几块独立的农作物区域.
样例输入:
4 4
RRRX
RXRX
XXXR
RXXX
样例输出:
3
这一道题运用了dfs的解题方法,依次搜索即可,其中标记思想也是很重要的,比较复杂。
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- char farm[509][509];//土地 farm: R代表农田, X代表杂草
- int sign[509][509];//状态 sign: 0代表未知, 1代表已知农田, -1代表已知杂草
- void dfs(int i,int j){//记录所有相邻的农田
- if(sign[i][j]) return;//搜过了
- if(farm[i][j]=='X')//如果有杂草
- sign[i][j]=-1;//记住杂草
- else{//否则
- sign[i][j]=1;//记住农田, 看看周围有无农田
- dfs(i-1,j);//上
- dfs(i+1,j);//下
- dfs(i,j-1);//左
- dfs(i,j+1);//右
- }
- }
- int main() {//主函数结束,返回0
- int n,m,cnt;//定义整数类型变量n,m,cnt
- cin>>n>>m;//输入n,m的值
- for(int i=1;i<=n;++i)//for循环,计数器i从1自增到n,共循环n次
- for(int j=1;j<=m;++j)//for循环,计数器j从1自增到m,共循环m次
- cin>>farm[i][j];//缓冲带: 用杂草把农田围起来
- for(int i=0;i<=n+1;++i)//for循环,计数器i从0自增到n+1,共循环n+2次
- sign[i][0]=sign[i][m+1]=-1;//记录
- for(int j=0;j<=m+1;++j)//for循环,计数器j从0自增到m+1,共循环m+2次
- sign[0][j]=sign[n+1][j]=-1;//记录
- //开搜
- for(int i=1;i<=n;++i)//for循环,计数器i从1自增到n,共循环n次
- for(int j=1;j<=m;++j)//for循环,计数器j从1自增到m,共循环m次
- if(!sign[i][j] && farm[i][j]=='R'){//发现了未被记录过的农田
- cnt++;//cnt自增1
- dfs(i,j);//以此为起点开始搜索
- }
- cout<<cnt<<endl;//输出cnt的值
- return 0;//主函数结束,返回0
- }
小蓝要给墙面上的n个矩形区域粉刷涂料, 给出每个矩形左下角和右上角的两个坐标(x1,y1, x2,y2). 请帮助小蓝计算下粉刷涂料的面积是多少, 如果矩形之间有重叠部分只计算一次.
例如: 有2个矩形,2个矩形左下角和右上角的两个坐标分别为: (2,2,9,5)、(6,1,12,9),
其粉刷涂料的面积是60.
输入描述:
先输入n的值;
再输入分为n行, 每行有四个正整数x1,y1, x2,y2 (1<x1<500, 1<y1<500, 1<x2<500, 1<y2<500,), 表示每个矩形左下角和右上角的两个坐标.输出描述:
输出一个整数,表示粉刷涂料的面积是多少.
样例输入:
2
2 2 9 5
6 1 12 9
样例输出:
60
法一:由于N是不确定的,也就是矩形的数量不确定,在矩形较多的情况下,互相覆盖的情况复杂,不容易用坐标值相减来进行计算。
于是我们把每个矩形看作是一个点阵。比如一个3x3的矩形,可以看作有3行3列共9个点组成的二维数组。
把整个坐标系,看作是一个大的二维数组,xy[0][0]即是坐标系的原点,行号代表x轴的值,列号看成y轴得值,那么每个矩形就是这个二维数组中的一部分。
因此每输入一个矩形的坐标,就可以根据坐标位置在二维数组中取对应得部分,为这些部分得每个数组元素中赋值为True,代表有面积.
最终数组中值为False得,说明没有矩形能覆盖到,值为True得说明只有一个矩形覆盖到了。
最终遍历整个点阵数组中的每个元素,累计有数字的元素个数,即最后的面积。
法二:二维前缀和容斥原理:
左上角(a,b),右下角(c,d)的矩形区域总和为:
s[c][d]-s[c][b]-s[a][d]+s[a][b]
把上述过程反过来, 就得到了到二维差分(本题中, 权 c=1):
m[a][b]+=c;
m[c][b]-=c;
m[a][d]-=c;
m[c][d]+=c;
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- bool xy[110][110];//二维数组,用来组成点阵信息
- int ans;//定义整数类型变量ans
- int main(){//主函数开始
- int n;//定义整数类型变量
- cin>>n;//输入n的值
- int x1,y1,x2,y2;//定义整数类型变量x1,x2,y1,y2
- for(int i=0;i<n;i++){
- cin>>x1>>y1>>x2>>y2;//循环输入每一个矩形的坐标信息
- for(int j=y1+1;j<=y2;j++)
- for(int k=x1+1;k<=x2;k++)
- xy[j][k]=1;//记录每个矩形点阵信息
- }
- for(int j=1;j<=109;j++){//for循环,计数器i从1自增到109,共循环109次
- for(int k=1;k<=109;k++)//for循环,计数器k从1自增到109,共循环109次
- if(xy[j][k]) ans++;//累积数组中为真的个数,即为面积
- }
- cout<<ans;//输出ans
- return 0;//主函数结束,返回0
- }
- #include<iostream>//调用输入输出流头文件
- using namespace std;//使用标准名字空间
- int a[509][509],n;
- int main(){//主函数开始
- int x1,y1,x2,y2;//定义整数类型x1,x2,y1,y2
- cin>>n;//输入n的值
- for(int i=0;i<n;i++){//for循环,计数器i从0自增到n-1,共循环n次
- cin>>x1>>y1>>x2>>y2;//输入x1,y1,x2,y2
- a[x1+1][y1+1]++;//a[x1+1][y1+1]自增1
- a[x2+1][y1+1]--;//a[x2+1][y1+1]自减1
- a[x1+1][y2+1]--;//a[x1+1][y2+1]自减1
- a[x2+1][y2+1]++;//a[x2+1][y2+1]自增1
- }
- long long sum=0;//定义长整数类型变量sum并初始化赋值为0
- for(int i=1;i<=20;++i)//for循环,计数器i从1自增到20,共循环20次
- for(int j=1;j<=20;++j){//for循环,计数器j从1自增到20,共循环20次
- a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];//a[i][j]自增a[i-1][j]+a[i][j-1]-a[i-1][j-1]
- //此时 a[i][j]里记录的就是每个点被覆盖的次数
- if(a[i][j]>0) sum++;//如果a[i][j]>0,sum自增1
- }
- cout<<sum<<endl;//输出sum的值
- return 0;//主函数结束,返回0
- }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。