作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
1.清華電腦系研究生考試上機07年試題解答(自己今天上午做的,有一個不能完成所有測試案例~)
清華大學電腦科學與技術系
2007 年碩士研究生招生複試
2007 年 3 月 24 日
注意事項:
1. 試題共三題,總計 100 分,考試時間為一個半小時。
2. 不得使用內建的電子裝置,包括筆記本、 USB 磁碟機、手機等;不得使用參考書籍和資料。
3. 編程環境為 Windows 2000 Professional + Visual Studio 6.0 ,只能使用 C/C++ 語言。
4. 每一題的輸入資料都從檔案 input.txt 中讀取,將結果輸出至檔案 output.txt ,請嚴格按照每一題的輸入輸出格式 。在考試過程中,我們恕不提供除試題中範例以外的測試資料,請自行產生輸入資料以對程式進行自測。
5. 在考試結束之前自行設定編譯環境和配置編譯參數,將所寫的程式編譯成可執行檔,檔案名稱在每一題中都有規定。產生的可執行檔將作為最終測試的唯一依據,若無法運行您的可執行檔,最終成績將記為零分。
6. 程式對每個測試資料的可用已耗用時間上限 1 秒,若逾時或結果錯誤,則該測試案例不能得分。
7. 在考試過程中,若電腦出現故障,請及時通知工作人員,以免耽誤您的考試時間。
8. 上機考試結束後,請勿馬上離開,工作人員將會直接進行現場測試,需要您的合作。
第一題(可執行檔名 program1.exe )
求正整數 N(N>1) 的質因數的個數。注意: 1 不是 N 的質因數:若 N 為質數, N 是 N 的質因數。相同的質因數需要重複計算。
如 120=2*2*2*3*5 ,共有 5 個質因數。
輸入:
正整數N ,1<N<109
輸出:
N 的質因數的個數
範例輸入:
120
範例輸出
5
#include<stdlib.h>#include<stdio.h>#include<math.h> int main(void){ int i=2,count=1; long int N; char buffer[10]; FILE *fp1,*fp2; fp1=fopen("input","r"); fgets(buffer,10,fp1); N=atol(buffer); while(i<=sqrt(N)) { for(;i<=sqrt(N);i++) if(N%i==0) { N=N/i; printf("%d*",i); count++; break; } } printf("%d",N); fp2=fopen("output","w"); itoa(count,buffer,10); fputs(buffer,fp2); rewind(fp2); fclose(fp1); fclose(fp2); return 0;}
第二題(可執行檔名:program2.exe )
對於一個十進位數A ,將A 轉換為位元,然後按位逆序排列,再轉換為十進位數B ,我們乘B 為A 的二進位逆序數 。
例如對於十進位數173 ,它的二進位形式為101011101 ,逆序排列得到10110101 ,其十進位數為181 ,181 即為173 的二進位逆序數
輸入:
一個1000 位( 即2999 ) 以內的十進位數。
輸出:
輸入的十進位數的二進位逆序數。
範例輸入:
173
範例輸出:
181
(下列程式只能忍受部分測試案例)
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h> #define MAX 100#define LEN 1000 long int process(long int N){ long int M=0; int count=0; int i,j; int temp[LEN]; int *p=temp; int tempr[LEN]; int *r=tempr; long int tmpnumber=N; for(i=0;tmpnumber!=0;tmpnumber/=2,i++) { *p++=tmpnumber%2; *r++=pow(2,i); count++; } for(i=0,j=count-1;i<count;i++,j--) { printf("temp[i]*tempr[j]=%d/n",temp[i]*tempr[j]); M+=temp[i]*tempr[j]; } return M;} int main(void){ long int N,M; FILE *fp1,*fp2; char buffer[MAX]; fp1=fopen("input","r"); fgets(buffer,MAX,fp1); N=atol(buffer); M=process(N); fp2=fopen("output","w"); ltoa(M,buffer,10); fputs(buffer,fp2); fclose(fp1); fclose(fp2); return 0;}
第三題(可執行檔名program3.exe )
有若干張郵票,要求從中選取最少的郵票張數湊成一個給定的總值。
如,有1 分,3 分,3 分,3 分,4 分五張郵票,要求湊成10 分,則使用3 張郵票:3 分、3 分、4 分即可。
輸入:
首先是要求湊成的郵票總值M ,M<100
然後是一個數N ,N 〈20 ,表示有N 張郵票。接下來是N 個正整數,分別表示這N 張郵票的面值,且以升序排列。
輸出:
能夠湊成總值M 的最少郵票張數。若無解,輸出0 。
範例輸入:
10 5 1 3 3 3 4
範例輸出:
3
分析:這是最簡單的背包問題,動態規劃的方法,寫得不是很規範,不過結果很不錯,線形複雜度 ~~
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h> #define MAX 100#define LEN 1000 void process(int M,int *a,int offset,int *flag){ if(offset>=0) { if(M-a[offset]>0) { if((M-a[offset])>=a[offset-1]) { flag[offset]=1; if(M>=0) process(M-a[offset],a,offset-1,flag); } else { if(M>=0) process(M,a,offset-1,flag); } } else if(M-a[offset]==0) flag[offset]=1; }} int main(void){ int N,M,i,number=0; int result; int count=0; FILE *fp1,*fp2; char tmp; int value[MAX]; int option[MAX]; int *p=value; int *flag=option; fp1=fopen("input","r"); fscanf(fp1,"%d %d",&M,&N); printf("M=%d,N=%d/n",M,N); for(i=0;i<N;i++) { fgetc(fp1); tmp=fgetc(fp1); value[i]=atoi(&tmp); printf("value=%d/n",value[i]); } process(M,p,N-1,flag); for(i=0;i<N;i++) { if(*flag++==1) { printf("%d",value[i]); count+=value[i]; number++; } } result=(count==M?number:0); fp2=fopen("output","w"); fprintf(fp2,"%d",result); fclose(fp1); fclose(fp2); return 0;}
2.清華電腦系研究生考試上機06年試題解答(自己今天下午做的,鬱悶之中。。。做的時間太長)
一、輸入:兩行
第一行:M和N
第二行:X
M和N是一個十進位數,M和N都在[2-36]之間,X是一個M進位數,X在[1-2*10^19]
輸出:一行
第一行:現在要求你將M進位數X轉換成N進位數輸出
輸入一:
16 10
F
輸出一:
15
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#define MAX 100/* 顯示錯誤資訊 */void printerror(char errno,char *num,int base1){ switch (errno) { case 1 : printf("/nError : Origin number %s(%d) is valid !!!/n",num,base1); break; case 2 : printf("/nError : radix (%d) is invalid !!!/n%s/n",base1,"Correct : radix>=2 and radix <=36"); break; }}/* 數制轉換函式 */void transnum(char *num,int base1,int base2){ int len,k,l,m,j,ibase1,ibase2; long inum=0; char temp[20]; double r=0; len = strlen(num); /* 數值的長度 */ ibase1 = base1; /* 數基1 */ if ((ibase1<2) || (ibase1>36)) printerror(2,"",base1); /* 有效嗎? */ ibase2 = base2; /* 數基2 */ if ((ibase2<2) || (ibase2>36)) printerror(2,"",base2); /* 有效嗎? */ for (j=0;j<len;j++) //這個迴圈是為了將要轉換的數字轉換為十進位 { /*******判斷字母或者數字,轉化為相應的數字******************/ r = pow(ibase1,len-j-1); /* 計算數基的冪指數 */ if (ibase1<=10) l = '9' - (10 - ibase1); /* 計算有效數範圍 */ else { /* 計算有效數範圍 */ m = 'a' + (ibase1 - 11); l = '9'; } if ((num[j]>=48) && (num[j]<=l)) /* 求每位元字的十進位值 */ k = num[j]-48; else if (ibase1>10) { /* 求每個字母所代表的十進位值 */ if ((num[j]>='A') && (num[j]<=m - 32)) k = num[j] - 'A'+10; else if ((num[j]>='a') && (num[j]<=m)) k = num[j] - 'a'+10; else printerror(1,num,base1); } else printerror(1,num,base1); /***************************************************/ inum += k * (int) r; /* 累加計算結果 */ } /* 輸出轉換結果 */ printf("%s(%d) = %s(%d)/n",num,ibase1,ltoa(inum,temp,ibase2),ibase2);}/* 主程式 */int main(void){ char number[MAX]; unsigned int m,n; static char num[10]; static int base1,base2; printf("m進位轉為n進位,請輸入m和n:/n"); scanf("%d %d", &m, &n); if(m<2||n<2) { printf("非法輸入!"); return 1; } getchar(); printf("萬能進位轉換程式。請輸入欲轉換的數:/n"); gets(number);/*將輸入的m進位數作為一個字串接收*/ strcpy(num,number); base1=m; base2=n; transnum(num,base1,base2);}
二、按照手機鍵盤輸入字母的方式,計劃所花費的時間
如:a,b,c都在“1”鍵上,輸入a只需要按一次,輸入c需要連續按三次。
如果連續兩個字元不在同一個按鍵上,則可直接按,如:ad需要按兩下,kz需要按6下
如果連續兩字元在同一個按鍵上,則兩個按鍵之間需要等一段時間,如ac,在按了a之後,需要等一會兒才能按 C。
現在假設每按一次需要花費一個時間段,等待時間需要花費兩個時間段。
現在給出一串字元,需要計划出它所需要花費的時間。
輸入一:bob
輸出一:7
輸入二:www
#include <stdlib.h>#include <stdio.h>#include <string.h>#define MAX 100int process(char *str,int len){ int flag=0; int delayflag=1; int i,j,delay=0; int length[9]={0,3,3,3,3,3,3,3,4}; int location=0; int count; int press=len; char *pstr=str; int *number; int table[27][2]; int (*p)[2]=table; number=malloc(sizeof(int)*(len+1)); for(i=0;i<len;i++) { number[i]=((*pstr++)-96); // printf("%d/n",number[i]); } number[i]=number[i-1]; for(i=0;i<=26;i++)//初始化表的其他行 { *(*(p+i))=i; switch(i) { case 3: case 6: case 9: case 12: case 15: case 19: case 22: case 26: *(*(p+i)+1)=1; break; default: *(*(p+i)+1)=0; break; } } for(i=0;i<len-1;i++) { printf("number[i]=%d/n",number[i]); printf("number[i+1]=%d/n",number[i+1]); delayflag=1; if((number[i]-number[i+1])<0) { for(j=number[i];j<number[i+1];j++) { if(*(*(p+1)+j)==1) delayflag=0; printf("delayflag=%d/n",delayflag); } if(delayflag) { delay+=1; } } else if((number[i]-number[i+1])>0) { for(j=number[i+1];j<number[i];j++) { if(*(*(p+1)+j)==1) delayflag=0; } if(delayflag) { delay+=1; } } else { delay+=1; } printf("delay=%d/n",delay); } for(i=0;i<len;i++) { count=0; j=number[i]; do { if((*(*(p+j)+1))==0) count+=1; }while((*(*(p+(j++))+1))==0); printf("count=%d",count); location+=(length[i+1]-count); printf("location=%d/n",location); } if(location==0) return (delay*2+location+len); else return (delay*2+location);}int main(void){ int len; char str[MAX]; char *p=str; gets(str); len=strlen(str); printf("%d/n",process(p,len)); return 0;}