往届试题
prev1
问题描述
小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。他的要求是:
- 各组的核桃数量必须相同
- 各组内必须能平分核桃(当然是不能打碎的)
- 尽量提供满足1,2条件的最小数量(节约闹革命嘛)
输入格式
输入包含三个正整数a, b, c,表示每个组正在加班的人数,用空格分开(a,b,c<30)
输出格式
输出一个正整数,表示每袋核桃的数量。
即求a,b,c的最大公约数,
a,b的最大公约数=a*b/gcd(a,b)
#include<stdio.h>
int gcd(int a,int b)
{
return b==0 ? a : gcd(b,a%b);
}
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int x=(a*b)/gcd(a,b);
int y=(a*c)/gcd(a,c);
int z=(x*y)/gcd(x,y);
printf("%d",z);
return 0;
}
prev2
问题描述
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示:
..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..
对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
输入格式
一个正整数 n (n<30) 表示要求打印图形的层数。
输出格式
对应包围层数的该标志。
#include<stdio.h>
char a[222][222];
void edge1(int n)
{
int i,j;int x=n*2+3;
for(i=1;i<=x;i++)
{
for(j=1;j<=x;j++)
{
if(a[i][j]=='$'){
if(a[i][j-1]=='#') a[i][j-1]='.';
//if(a[i][j+1]=='#') a[i][j+1]='.';
if(a[i-1][j]=='#') a[i-1][j]='.';
//if(a[i+1][j]=='#') a[i+1][j]='.';
if(a[i-1][j-1]=='#') a[i-1][j-1]='.';
// if(a[i+1][j+1]=='#') a[i+1][j+1]='.';
// if(a[i-1][j+1]=='#') a[i-1][j+1]='.';
// if(a[i+1][j-1]=='#') a[i+1][j-1]='.';
}
}
}
}
void edge2(int n)
{
int i,j;int x=n*2+3;
for(i=1;i<=x;i++)
{
for(j=1;j<=x;j++)
{
if(a[i][j]=='.'){
if(a[i][j-1]=='#') a[i][j-1]='$';
//if(a[i][j+1]=='#') a[i][j+1]='$';
if(a[i-1][j]=='#') a[i-1][j]='$';
//if(a[i+1][j]=='#') a[i+1][j]='$';
if(a[i-1][j-1]=='#') a[i-1][j-1]='$';
// if(a[i+1][j+1]=='#') a[i+1][j+1]='$';
// if(a[i-1][j+1]=='#') a[i-1][j+1]='$';
// if(a[i+1][j-1]=='#') a[i+1][j-1]='$';
}
}
}
}
void work(int n)
{
int x=n*2+3;int y=x;
a[x][y]='$';//从中心点开始向上下左右扩张
a[x+1][y]='$';a[x+2][y]='$';
a[x][y+1]='$';a[x][y+2]='$';
a[x-1][y]='$';a[x-2][y]='$';
a[x][y-1]='$';a[x][y-2]='$';
int i;
for(i=1;i<=n;i++)
{
edge1(n);edge2(n);
//将“十字”周围填上"."
//将"." 用"$"包围
}
}
void print(char c)
{
if(c=='#') printf(".");
else printf("%c",c);
return ;
}
int main()
{
int n,i,j;
scanf("%d",&n);
//预处理,将所有格子填上#,表示未修改
for(i=1;i<=(5+4*n);i++)
{
for(j=1;j<=(5+4*n);j++)
{
a[i][j]='#';
}
}
work(n);
int m=(5+4*n)/2;
//打印前一半
for(i=1;i<=m+1;i++)
{
for(j=1;j<=m+1;j++)
{
print(a[i][j]);
}
for(j=m;j>0;j--)
{
print(a[i][j]);
}
printf("\n");
}
//打印后一半
for(i=m;i>0;i--)
{
for(j=1;j<=m+1;j++)
{
print(a[i][j]);
}
for(j=m;j>0;j--)
{
print(a[i][j]);
}
printf("\n");
}
return 0;
}
prve3
问题描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
从标准输入读入一个正整数N (N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
#include<stdio.h>
#include<string.h>
int n,tot,len;
int list[]={0,1,2,3,4,5,6,7,8,9};
int getnum(int x,int y)
{
int i,sum=0;
for(i=x;i<=y;i++)
{
sum=sum*10+list[i];
}
return sum;
}
void check()
{
int a,b,c,i,j;
//n=a+b/c
for(i=1;i<=len;i++)
{//枚举前i个数作为a
a=getnum(1,i);
for(j=(9-i)/2;j<9-i;j++)
{//枚举后面的bc
b=getnum(i+1,i+j);
c=getnum(i+j+1,9);
if(b%c){
continue;
}
if(a+b/c==n){
tot++;
//printf("%d %d %d\n",a,b,c);
}
}
}
return ;
}
void swap(int a,int b)
{
int t=list[a];
list[a]=list[b];
list[b]=t;
return ;
}
void qpl(int s,int e)
{//一共要排e个数,现在要排第s个
if(s > e){
check();
//排满9个数开始验证
}else{
int i;
for(i=s;i<=e;i++)
{//让第s个数依次和后面的数交换
swap(s,i);
qpl(s+1,e);
swap(s,i);
}
}
}
int main()
{
scanf("%d",&n);
char k[9];
sprintf(k,"%d",n);
//将n转为字符串k
len=strlen(k);
qpl(1,9);
//全排列
printf("%d",tot);
return 0;
}
prev4
问题描述
如下图所示,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。
输出格式
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
这题我想不明白为什么搜索搜出来的区域一定是可以把整个区域分成两部分的,会不会存在分成多个区域的情况呢?望解答。
#include<stdio.h>
int n,m,befor=0,ans=222;
//befor记录所有格子值的和,ans初始值为INF
int a[22][22],c[4]={1,0,-1,0},d[4]={0,1,0,-1};
bool b[22][22];
//b记录格子有没有被搜索过
void dfs(int x,int y,int sum,int t)
{
//从第一个位置开始搜索
//sum记录目前走过的格子值的和,t记录搜索的步数
if(sum==befor){
if(t<ans){
ans=t;
}
}
int i,xx,yy;
for(i=0;i<4;i++)
{
xx=x+c[i];
yy=y+d[i];
if(yy<1||yy>m||xx<1||xx>n||b[xx][yy]==1||sum+a[xx][yy]>befor){
continue;
}
b[x][y]=1;
dfs(xx,yy,sum+a[xx][yy],t+1);
b[x][y]=0;
}
return ;
}
int main()
{
scanf("%d%d",&m,&n);
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
b[i][j]=0;
befor+=a[i][j];
}
}
befor/=2;
dfs(1,1,a[1][1],1);
if(ans==222){
printf("0");
}else{
printf("%d",ans);
}
return 0;
}