浙大计算机研究生复试上机考试-2009年

时间:2022-05-03 06:40:14
//hdu 3782 3783 3784 3785 3786

/************************************************************************/
/* xxx定律-hdu 3782

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 525 Accepted Submission(s): 438


Problem Description
对于一个数n,如果是偶数,就把n砍掉一半;如果是奇数,把n变成 3*n+ 1后砍掉一半,直到该数变为1为止。
请计算需要经过几步才能将n变到1,具体可见样例。


Input
测试包含多个用例,每个用例包含一个整数n,当n为0 时表示输入结束。(1<=n<=10000)


Output
对于每组测试用例请输出一个数,表示需要经过的步数,每组输出占一行。


Sample Input
3
1
0


Sample Output
5
0


Source
浙大计算机研究生复试上机考试-2009年 */
/************************************************************************/

#include "stdio.h"
#include"math.h"

int main()
{
int a,b;
while(scanf("%d",&a)!=EOF&&a)
{
int cnt=0;
while (a!=1)
{
if(a%2)
{
a=a*3+1;
a/=2;
}
else
a/=2;
cnt++;
}
printf("%d\n",cnt);
}
}


/************************************************************************/
/* ZOJ hdu 3783

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 464 Accepted Submission(s): 353


Problem Description
读入一个字符串,字符串中包含ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出,当某个字符用完时,剩下的仍然按照ZOJ的顺序输出。


Input
题目包含多组用例,每组用例占一行,包含ZOJ三个字符,当输入“E”时表示输入结束。
1<=length<=100。


Output
对于每组输入,请输出一行,表示按照要求处理后的字符串。
具体可见样例。


Sample Input
ZZOOOJJJ
ZZZZOOOOOJJJ
ZOOOJJ
E


Sample Output
ZOJZOJOJ
ZOJZOJZOJZOO
ZOJOJO


Source
浙大计算机研究生复试上机考试-2009年 */
/************************************************************************/

#include "iostream"
#include"string"
using namespace std;

int main()
{
char str[105];
while (scanf("%s",str)!=EOF&&strcmp(str,"E"))
{
int z,o,j;
z=o=j=0;
for (int i=0;i<strlen(str);i++)
{
if(str[i]=='Z')
z++;
else if(str[i]=='O')
o++;
else if (str[i]=='J')
j++;
}
while (z>0||o>0|j>0)
{
if(z-->0)
printf("Z");
if(o-->0)
printf("O");
if (j-->0)
printf("J");
}
printf("\n");
}
}

/************************************************************************/
/* 继续xxx定律-hdu 3784

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 685 Accepted Submission(s): 197


Problem Description
当n为3时,我们在验证xxx定律的过程中会得到一个序列,3,5,8,4,2,1,将3称为关键数,5,8,4,2称为覆盖数。现在输入n个数字a[i],根据关键数与覆盖数的理论,我们只需要验证其中部分数就可以确定所有数满足xxx定律,输出输入的n个数中的关键数。如果其中有多个关键数的话按照其输入顺序的逆序输出。


Input
输入数据包含多个用例,每个用例首先包含一个整数n,然后接下来一行有n个整数a[i],其中:
1<=n<=500
1<a[i]<=1000


Output
请计算并输出数组a中包含的关键数,并按照其输入顺序的逆序输出,每个用例输出占一行。


Sample Input
3
3 8 4
5
3 8 4 7 15
5
3 8 4 15 7
0


Sample Output
3
15 7 3
7 15 3


Source
浙大计算机研究生复试上机考试-2009年
*/
/************************************************************************/

#include"iostream"
using namespace std;
#define N 1010
int a[N];
bool v[200000];
int main()
{
int x,i,j,n;
while (scanf("%d",&n)!=EOF&&n)
{
memset(v,false,sizeof(v));
for (i=0;i<n;i++)
{
scanf("%d",&a[i]);
x=a[i];
while (x!=1)
{
if(x%2)
{
x=x*3+1;
x/=2;
}
else
x/=2;
v[x]=true;
}
}
bool first=true;
for (i=n-1;i>=0;i--)
{
if (!v[a[i]])
{
if(!first)
cout<<" ";
printf("%d",a[i]);
first=false;
}
else
continue;
}
printf("\n");
}
}

/************************************************************************/
/* 寻找大富翁-hdu 3785

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 765 Accepted Submission(s): 413


Problem Description
浙江桐乡乌镇共有n个人,请找出该镇上的前m个大富翁.


Input
输入包含多组测试用例.
每个用例首先包含2个整数n(0<n<=100000)和m(0<m<=10),其中: n为镇上的人数,m为需要找出的大富翁数, 接下来一行输入镇上n个人的财富值.
n和m同时为0时表示输入结束.


Output
请输出乌镇前m个大富翁的财产数,财产多的排前面,如果大富翁不足m个,则全部输出,每组输出占一行.


Sample Input
3 1
2 5 -1
5 3
1 2 3 4 5
0 0


Sample Output
5
5 4 3


Source
浙大计算机研究生复试上机考试-2009年 */
/************************************************************************/

#include "iostream"
#include "algorithm"
using namespace std;

int a[100002];
int m,n;
int main()
{
int i;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
for (i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
printf("%d",a[n-1]);
for (i=1;i<m;i++)
printf(" %d",a[n-i-1]);
cout<<endl;
}
}

/************************************************************************/
/*3785- 寻找大富翁(寻找第k大的数)
*************************************************************************/
//the k max number
//@Author:zrq sophia
#include "iostream"
#include "algorithm"
using namespace std;

int a[100002];
int c[15];
int m,n;


int Partition(int left,int right,int k)//find array 中的第k大数
{
int base=a[left];//basic element
int l,r;
l=left,r=right;
while(l<r)
{
while(l<r&&a[r]>base)r--;
if(l<r)
a[l++]=a[r];
while(l<r&&a[l]<=base)l++;
if(l<r)
a[r--]=a[l];
}
a[l]=base;
int index=right-r+1;//base在是第index大的数
if(index>k)
return Partition(r+1,right,k);
else if(index<k)
return Partition(left,r-1,k-index);
return base;
}

int main()
{
int i;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
for (i=0;i<n;i++)
scanf("%d",&a[i]);
int b= Partition(0,n-1,m);
int j=0;
for(i=0;i<n;i++)
{
if(a[i]>b)
c[j++]=a[i];
}
bool flag=false;
sort(c,c+j);
if(j>=1)
{
printf("%d",c[j-1]);
flag=true;
}
for(i=1;i<j;i++)
printf(" %d",c[j-1-i]);
if(!flag)
{
printf("%d",b);
j++;
}
while(++j<=m)
printf(" %d",b);

cout<<endl;
}
}

/************************************************************************/
/* 找出直系亲属

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 411 Accepted Submission(s): 171


Problem Description
如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,则A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,则A,B是C的great-grandparent,C是A,B的great-grandchild,之后再多一辈,则在关系上加一个great-。


Input
输入包含多组测试用例,每组用例首先包含2个整数n(0<=n<=26)和m(0<m<50), 分别表示有n个亲属关系和m个问题, 然后接下来是n行的形式如ABC的字符串,表示A的父母亲分别是B和C,如果A的父母亲信息不全,则用-代替,例如A-C,再然后是m行形式如FA的字符串,表示询问F和A的关系。
当n和m为0时结束输入。


Output
如果询问的2个人是直系亲属,请按题目描述输出2者的关系,如果没有直系关系,请输出-。
具体含义和输出格式参见样例.


Sample Input
3 2
ABC
CDE
EFG
FA
BE
0 0


Sample Output
great-grandparent
-


Source
浙大计算机研究生复试上机考试-2009年

*/
/************************************************************************/
#include "iostream"
#include "string"
#include "algorithm"
using namespace std;
#define INF 1000000
#define min(a,b) a<b?a:b
char tree['Z'+10][2];

int Dfs(char a,char b,int level)
{
//分别从a和b往下找
if(a=='-'||tree[a][0]=='-'&&tree[a][1]=='-')
return INF;
if(tree[a][0]==b||tree[a][1]==b)
return level+1;
int left=Dfs(tree[a][0],b,level+1);
int right=Dfs(tree[a][1],b,level+1);
return min(left,right);
}
int main()
{
string str;
int n,m,i,j;
while (scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
{
memset(tree,'-',sizeof(char)*2*('Z'+10));
for(i=0;i<n;i++)
{
cin>>str;
tree[str[0]][0]=str[1];
tree[str[0]][1]=str[2];
}
for(i=0;i<m;i++)
{
cin>>str;
int level1=Dfs(str[0],str[1],0);
int level2=Dfs(str[1],str[0],0);
int level=level1>=INF?-level2:level1;
if(abs(level)>=INF)
{
printf("-\n");
continue;
}
while (level++<-2)
printf("great-");
level--;
if(level==-1)
printf("parent\n");
else if(level==-2)
printf("grandparent\n");

while (level-->2)
printf("great-");
level++;
if (level==2)
printf("grandchild\n");
else if(level==1)
printf("child\n");
}
}
}

hdu 3786

//逆向思考更简单,建树可知每个node对应一个孩子,这里把孩子记为parent,只要顺着parent往上爬着找就行了
//@Author:zrq sophia
#include "iostream"
#include "stdio.h"
#include "string"
#include"memory.h"
#include "algorithm"
using namespace std;
#define INF 30
#define min(a,b) a<b?a:b
char parent['Z'+10];//这棵树中的parent与题目描述的父子关系正好相反

int cha(char c1,char c2)
{
int level=0;
while(c1!=c2&&c1!='-')
{
c1=parent[c1];
level++;
}
if(c1=='-')
return INF;
return level;
}

int main()
{
string str;
int n,m,i,j;
while (scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
memset(parent,'-',sizeof(char)*('Z'+10));
for(i=0;i<n;i++)
{
cin>>str;
parent[str[1]]=str[0];
parent[str[2]]=str[0];
}
for(i=0;i<m;i++)
{
cin>>str;
int level1=cha(str[0],str[1]);
int level2=cha(str[1],str[0]);
int level=level2>=INF?-level1:level2;
if(abs(level)>=INF||abs(level)==0)
{
printf("-\n");
continue;
}
while (level++<-2)
printf("great-");
level--;
if(level==-1)
printf("parent\n");
else if(level==-2)
printf("grandparent\n");

while (level-->2)
printf("great-");
level++;
if (level==2)
printf("grandchild\n");
else if(level==1)
printf("child\n");
}
}
}