蓝桥杯------历届真题
《1》核桃的数量
小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。他的要求是:
1. 各组的核桃数量必须相同
2. 各组内必须能平分核桃(当然是不能打碎的)
3. 尽量提供满足1,2条件的最小数量(节约闹革命嘛)
#include<stdio.h> int f(int a,int b) { int i,t; if(b>a) { t=a; a=b; b=t; } for(i=a;;i=i+a) { if(i%a==0&&i%b==0)break; } return i; } int main() { int a,b,c,r; scanf("%d%d%d",&a,&b,&c); r=f(a,b); r=f(r,c); printf("%d\n",r); return 0; }
《2》打印十字图
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:
................
...
.....
...
...................
对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
..
................
...
.....
...
...................
#include<stdio.h> char a[10000][10000]; int main() { int n,i,j,k,b,r,c,d,t,m; scanf("%d",&n); int row=9+(n-1)*4,cll=row,mid=row/2+1; k=n-1; for(i=1;i<=row/2;k--) { m=5+4*k; b=(row-m)/2; // if(i%2==1) // { a[i][mid]='$'; for(r=mid+1;r<=row-b;r++) { a[i][r]=a[i][row-r+1]='$'; } if(b==2) { a[i][r]=a[i][row-r+1]='.';r++; a[i][r]=a[i][row-r+1]='.';r++; } else { a[i][r]=a[i][row-r+1]='.';r++;t=r+2; for(;r<=t;r++)a[i][r]=a[i][row-r+1]='$'; for(;r<=row;) { a[i][r]=a[i][row-r+1]='.';r++; a[i][r]=a[i][row-r+1]='$';r++; } } i++; // } // else // { c=m-2;d=(cll-c)/2; if(m==1) { a[i][mid]='$';r=mid+1; } else { a[i][mid]='.'; for(r=mid+1;r<=row-d;r++) a[i][r]=a[i][row-r+1]='.'; a[i][r]=a[i][row-r+1]='$';r++; } //if(d-1==2) // { a[i][r]=a[i][row-r+1]='.';r++; a[i][r]=a[i][row-r+1]='.';r++; // } for(;r<=row;) { a[i][r]=a[i][row-r+1]='.';r++; a[i][r]=a[i][row-r+1]='$';r++; } // } i++; } a[i][mid]='$'; for(r=mid+1;r<=mid+2;r++)a[i][r]=a[i][row-r+1]='$'; for(;r<=row;) { a[i][r]=a[i][row-r+1]='.';r++; a[i][r]=a[i][row-r+1]='$';r++; } for(i=1;i<=row/2+1;i++) { for(j=1;j<=cll;j++) { printf("%c",a[i][j]); } printf("\n"); } for(i=row/2;i>0;i--) { for(j=1;j<=cll;j++) { printf("%c",a[i][j]); } printf("\n"); } return 0; }
《3》 带分数
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
从标准输入读入一个正整数N (N<1000*1000)
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
/* 问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714。 还可以表示为:100 = 82 + 3546 / 197。 注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。 类似这样的带分数,100 有 11 种表示法。 输入格式 从标准输入读入一个正整数N (N<1000*1000) 输出格式 程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。 注意:不要求输出每个表示,只统计有多少表示法! 样例输入1 100 样例输出1 11 样例输入2 105 样例输出2 6 */ #include<stdio.h> #include<string.h> #include<math.h> #define M 9 int back[M+1],flag[M+1],sum;
//求常数项的标志 int f1(int a) { int i,j=0; memset(flag,0,sizeof(flag)); while(a) { j++; i=a%10; if(i==0 || flag[i]==1)return 0; else flag[i]=1; a/=10; } return j; }
//求分子或分母是否符合要求 int f2(int a) { memcpy(back,flag,sizeof(flag)); int i,j=0; while(a) { j++; i=a%10; if(i==0 || back[i]==1)return 0; else back[i]=1; a/=10; } return j; }
//求分子a和分母b是否满足要求 int f3(int a,int b) { memcpy(back,flag,sizeof(flag)); int i; while(a) { i=a%10; if(i==0 || back[i]==1)return 0; else back[i]=1; a/=10; } while(b) { i=b%10; if(i==0 || back[i]==1)return 0; else back[i]=1; b/=10; } for(i=1;i<=M;i++) { if(back[i]==0)return 0; } return 1; } int main() { int N,i,j,k,nz,nfz,nfm,a,b,fz,fm,fzup; scanf("%d",&N); sum=0; for(i=1;i<=N;i++) { if((nz=f1(i))==0)continue; fzup=pow(10,M-nz+1)-1; a=N-i;b=1; for(k=2;k<=98765&&a*k<fzup;k++) { if((nfz=f2(k))==0)continue; if(f3(a*k,k)==1) { sum++; // printf("zshu=%d fz=%d fm=%d\n",i,a*k,k); } } } printf("%d\n",sum); return 0; }
《4》剪格子
如下图所示,3 x 3 的格子中填写了一些整数。
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 3|
+--+--+--+
我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0。
程序先读入两个整数 m n 用空格分割 (m,n<10)。
表示表格的宽度和高度。
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。
10 1 52
20 30 1
1 2 3
1 1 1 1
1 30 80 2
1 1 1 100
#include<stdio.h> #include<string.h> int xy[][2]={{1,0},{0,1},{-1,0},{0,-1}};//下一步方向{x,y} int a[11][11],vis[11][11],sum,m,n;//m列n行 //检查{x,y}是否可行 int chack(int x,int y,int num) { if(x<1 ||x>n || y<1 || y>m) return 0; if((num+a[x][y])>sum) return 0; if(vis[x][y]) return 0; return 1; } int f1(int x,int y,int num)//遍历 { if(num==sum)return 1; int i,res=0,xn,yn; for(i=0;i<4;i++)//尝试四个方向 { xn=x+xy[i][0]; yn=y+xy[i][1]; if(chack(xn,yn,num)) { vis[xn][yn]=1; int res=f1(xn,yn,num+a[xn][yn]); if(res>0)return res+1; vis[xn][yn]=0; } } return 0; } int main() { scanf("%d%d",&m,&n); int i,j; sum = 0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { scanf("%d",&a[i][j]); sum+=a[i][j]; } } if(sum%2==1) printf("0\n");//如果所有格子的和不能分成相等的半 else { sum/=2; memset(vis,0,sizeof(vis));//从左上角开始遍历 vis[1][1]=1; printf("%d\n",f1(1,1,a[1][1])); } return 0; }
《5》 翻硬币
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:**oo***oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000
一个整数,表示最小操作步数。
o****o****
*o***o**o***
总结:注意:
在测试代码的时候用本地文件存储数据然后读取数据是较快的测试方法,但是要注意再提交代码的时候要将相应的对文件进行操作的代码注释掉
否在提交代码会因找不到相应的文件而报错
参考代码
#include<stdio.h> #include<string.h> #define M 10100 char ch1[M],ch2[M]; int main() { int i,j,len,step; FILE *f; // f=fopen("testnum.txt","r+"); // fscanf(f,"%s\n",&ch1); scanf("%s\n",&ch1); //getchar(); // fscanf(f,"%s",&ch2); scanf("%s",&ch2); len=strlen(ch1); step=0; char c; for(i=0;i<len;i++) { if(ch1[i]==ch2[i])continue; if(ch1[i]=='*')ch1[i]='o'; else ch1[i]='*'; if(ch1[i+1]=='*')ch1[i+1]='o'; else ch1[i+1]='*'; step++; } printf("%d\n",step); // fclose(f); return 0; }