蓝桥杯真题练习
前言
为准备考研复试上机考试,练习蓝桥杯真题,记录每一题的思路、问题及代码
一、2023年软件类省赛C/C++大学A组
1.平方差
平方差n=m^2 - k^2=(m-k)(m+k),令m-k=x,m+k=y,
则可得m=(x+y)/2,n=(x-y)/2。若m,n均为整数,则x+y,x-y均为偶数,则x和y同奇偶(奇+奇=偶,奇-奇=偶,偶+偶=偶,偶-偶=偶)。
进一步:n=xy
1)x和y同偶:x和y均为2的倍数,则n为4的倍数
2)x和y同奇:n=xy仍为奇数
综上:n为4的倍数,或奇数
#include<stdio.h>
int main()
{
int L,R;
scanf("%d %d", &L, &R);
int count=0;//计数
for(int i=L;i<=R;i++){//判断是不是平方差:是4的倍数,或是奇数
if(i%4==0 || i%2!=0)
count++;
}
printf("%d\n",count);
return 0;
}
2.更小的数
自己的思路:遍历字符串的每一个子串,将该子串逆置,将字符串转为数,比较逆置后的数和原来的数的大小,代码如下
结果输出为0,错误
#include<stdio.h>
#include<string.h>
int toNum(char *s){//字符串转整数
int result=0;
for(int i=0;s[i]!='\0';i++){
result=result*10;
result+=i-'0';
}
return result;
}
void reverse(char *s,int a,int b){//将下标a到b的子串翻转
char temp;
while(a<b){
temp=s[a];
s[a]=s[b];
s[b]=temp;
a++;b--;
}
}
int main()
{
printf("**************************\n");
printf("dotcpp.com\n");
printf("**************************\n");
char s[100];
char snew[100];
scanf("%s",s);
//字符串转整数
int x=toNum(s);
int y,count=0;
int len=strlen(s);
for(int i=0;i<=len-2;i++){
for(int j=i+1;j<=len-1;j++){
strcpy(snew,s);
reverse(snew,i,j);
y=toNum(snew);
if(y<x)
count++;
}
}
printf("%d\n",count);
return 0;
}
看答案的思路:
遍历每个子串,比较子串第一个字符和最后一个字符的大小。如果第一个字符大于最后一个字符,则该子串逆置之后的数一定小于原数;如果第一个字符等于最后一个字符,则继续看第二个字符和倒数第二个字符的大小,如果第二个字符大于倒数第二个字符,则该子串逆置之后的数一定小于原数(找到一个就可以跳出这个子串的循环了,继续找下一个子串);如果第二个字符小于倒数第二个字符,则该子串逆置之后的数一定大于原数,继续找下一个子串;如果第二个字符等于倒数第二个字符,则继续向内找。
代码如下:
#include<stdio.h>
#include<string.h>
int main()
{//后面的数比前面的小则交换后的数小
char s[5000];
scanf("%s",s);
int count=0;
int len=strlen(s);
int a,b;
for(int i=0;i<=len-2;i++){
for(int j=i+1;j<=len-1;j++){//遍历每个子串
if(s[i]>s[j])
count++;
else if(s[i]==s[j]){
a=i+1;
b=j-1;
while(a<b){
if(s[a]>s[b]){
count++;
break;
}
else if(s[a]<s[b])//若后面的数大于前面的数则pass
break;
a++;
b--;
}
}
}
}
printf("%d\n",count);
return 0;
}