前言:以下代碼部分僅供參考,C語言解答部分全部來自網友,Java語言部分部分參考自網友,對於答案的正確性不能完全保證。
試題1
數論中有著名的四方定理:所有自然數至多只要用四個數的平方和就可以表示。 我們可以通過計算機驗證其在有限范圍的正確性。 對於大數,簡單的循環嵌套是不適宜的。下面的代碼給出了一種分解方案。 請仔細閱讀,填寫空缺的代碼(下划線部分)。 注意:請把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。 直接寫在題面中不能得分。 int f(int n, int a[], int idx) { if(______________) return 1; // 填空1 if(idx==4) return 0; for(int i=(int)sqrt(n); i>=1; i--) { a[idx] = i; if(_______________________) return 1; // 填空2 } return 0; } int main(int argc, char* argv[]) { for(;;) { int number; printf("輸入整數(1~10億):"); scanf("%d",&number); int a[] = {0,0,0,0}; int r = f(number, a, 0); printf("%d: %d %d %d %d\n", r, a[0], a[1], a[2], a[3]); } return 0; } a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + a[3]*a[3] == n f(n, a, idx + 1) == 1
來自網友:
本題滿分: 9分
填空1: (3分)
n==0
或者:0==n
填空2: (6分)
f(n-i*i, a, idx+1)
或者:
f(n-i*i, a, idx+1) > 0
f(n-i*i, a, idx+1) == 1
試題2
在對文本進行簡單加密的時候,可以選擇用一個n位的二進制數,對原文進行異或運算。 解密的方法就是再執行一次同樣的操作。 加密過程中n位二進制數會循環使用。並且其長度也可能不是8的整數倍。 下面的代碼演示了如何實現該功能。 請仔細閱讀,填寫空缺的代碼(下划線部分)。 void f(char* buf, unsigned char* uckey, int n) { int i; for(i=0; i<n; i++) buf[i] = buf[i] ^ uckey[i]; //異或運算,即:buf[i] ^= uckey[i] } int main(int argc, char* argv[]) { char p[] = "abcd中國人123"; // 待加密串 char* key = "11001100010001110"; //以串的形式表達的密匙,運算時要轉換為按位存儲的形式。 int np = strlen(p); int nk = strlen(key); unsigned char* uckey = (unsigned char*)malloc(np); // unsigned char是無符號字節型,char類型變量的大小通常為1個字節(1字節=8個位) // 密匙串需要按位的形式循環拼入 uckey中 int i; for(i=0; i<np*8; i++) { if(key[i%nk]=='1') ______; // 填空1按位或 else ______; // 填空2按位與 } f(p, uckey, strlen(p)); f(p, uckey, strlen(p)); printf("%s\n", p); free(uckey); return 0; } uckey[i/8] |= (unsigned char)0x80 >> (i%8) uckey[i/8] &= ~((unsigned char)0x80 >> (i%8))
本題滿分:14分
填空1:(7分)
uckey[i/8] |= (unsigned char)0x80 >> (i%8); //>>表示右移位,位邏輯運算符:&按位與,|按位或,^按位異或,~取反,移位運算符:<<左移,>>右移
從數學上看,左移1位等於乘以2,右移1位等於除以2,然后再取整,移位溢出的丟棄
填空2:(7分)
uckey[i/8] &= ~((unsigned char)0x80 >> (i%8));
注意所有邏輯等價形式都是正確的答案,比如可以使用左移位:
(unsigned char)0x80 >> 2 等價於:0x01 << 5
試題3
為什么1小時有60分鍾,而不是100分鍾呢?這是歷史上的習慣導致。 但也並非純粹的偶然:60是個優秀的數字,它的因子比較多。 事實上,它是1至6的每個數字的倍數。即1,2,3,4,5,6都是可以除盡60。 我們希望尋找到能除盡1至n的的每個數字的最小整數。 不要小看這個數字,它可能十分大,比如n=100, 則該數為: 69720375229712477164533808935312303556800 請編寫程序,實現對用戶輸入的 n (n<100)求出1~n的最小公倍數。 例如: 用戶輸入: 6 程序輸出: 60 用戶輸入: 10 程序輸出: 2520 要求考生把所有函數寫在一個文件中。調試好后,存入與考生文件夾下對應題號的“解答.txt”中即可。 相關的工程文件不要拷入。 對於編程題目,要求選手給出的解答完全符合ANSI C標准,不能使用c++特性; 不能使用諸如繪圖、中斷調用等硬件相關或操作系統相關的API。
import java.math.BigInteger; import java.util.Scanner; public class Main { public void getResult(int n) { BigInteger temp1 = BigInteger.ONE; BigInteger temp2 = BigInteger.ONE; BigInteger temp3 = BigInteger.ONE; for(int i = 2;i <= n;i++) { temp1 = temp3; temp2 = new BigInteger(""+i); temp3 = temp1.gcd(temp2); temp3 = temp1.multiply(temp2).divide(temp3); } System.out.println(temp3); } public static void main(String[] args) { Main test = new Main(); Scanner in = new Scanner(System.in); int n = in.nextInt(); test.getResult(n); } }
來自網友C語言版:
解答: 最小公倍數就是所有質數的相應冪的積 比如N=10 小於10的質數有2,3,5,7 對應的最大冪是:3,2,1,1 則最小公倍數是:2^3x3^2x5^1x7^1 = 2520 #include <iostream> #include <cstring> #include <cmath> using namespace std; int a[50] = {0};//存素數 bool vis[100]; int b[50] = {0};//存冪次 void init_prim()//求小於100的所有素數存入數組a { int i,j,k; int m = (int)(sqrt(100.0)+0.5); memset(vis,0,sizeof(vis)); vis[0] = 1; vis[1] = 1;//必須加上,否則第一個素數別認為是1 for(i=2; i<=m; i++) if(!vis[i]) { for(j=2*i; j<=100; j+=i) vis[j] = 1; } int t = 0; for(k=0; k<100; k++) if(!vis[k]) a[t++] = k; } int main() { int i,j,k; init_prim(); int n; //2^6 = 64,2^7 = 128;由於n最大100,冪次最大6 // for(i=0 ; i<100; i++)//素數沒問題 // if(!vis[i]) // cout<<i<<endl; // while(1); while(cin>>n) { memset(b,0,sizeof(b)); for(i=0; i<=n&&a[i]<=n; i++)//”1到n素數個數小於n的一半 “不對,3有兩個素數 { // cout<<a[i]<<"-----"<<endl; for(j=1; j<=6; j++) { if(pow((double)a[i],(double)j)>(double)n) { b[i] = j -1;//b的下標不必新開 break; } else if(pow((double)a[i],(double)j) == (double)n)//必須分開 { b[i] = j; break; } } } //不知道是不是pow函數的問題,把ans定義為int得出的結果出問題,double就對了 double ans = 1; for(k=0; k<i; k++) { //cout<<a[k]<<"........"<<b[k]<<endl; ans *= pow((double)a[k],(double)b[k]); } cout<<(int)ans<<endl; } return 0; } //該程序 到25時就溢出,ans換位long long前幾個就錯誤啦,此時需要把pow函數換掉 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; const int N = 105; int n; int a[N][50]; int b[N] = {0}; void multiply() { int i,j,k; memset(a,0,sizeof(a)); for(i=3; i<=100; i++) { /* 下面的是直接按平常的乘法,乘數的一位乘以被乘數的每一位並處理進位;另外是乘數整體乘以被乘數的每一位最后統一處理進位 */ int temp = 0; a[i][0] = 1;//很重要 for(j=2; j<=i; j++) { int c = 0; for(k=0; k<50; k++)//最大不超過160位 ,目前是100!,最后除以3等50 { temp = a[i][k]*b[j] + c; a[i][k] = temp%1000; c = temp/1000; } } } } void printData(int n) { int i,j,k; for(i=49; i>=0; i--) if(a[n][i]) break; cout<<a[n][i];//第一個不輸出前導0 for(j=i-1; j>=0; j--) printf("%03d",a[n][j]); cout<<endl; } int main() { int i, j, k; for(i=0; i<N; i++) b[i] = i; for(i=2; i<N; i++) for(j=i+1; j<=N; j++) { if(b[j]%b[i]==0) b[j] /= b[i]; //cout<<b[j]<<endl; } //for(i=0; i<100; i++) // cout<<b[i]<<endl; //while(1); multiply(); while(cin>>n) { if(n==1||n==2) { cout<<n<<endl; continue; } printData(n); } return 0; }
試題4
為解決交通難題,某城市修建了若干條交錯的地鐵線路,線路名及其所屬站名如stations.txt所示。 線1 蘋果園 .... 四惠東 線2 西直門 車公庄 .... 建國門 線4 .... 其中第一行數據為地鐵線名,接下來是該線的站名。 當遇到空行時,本線路站名結束。 下一行開始又是一條新線....直到數據結束。 如果多條線擁有同一個站名,表明:這些線間可以在該站換車。 為引導旅客合理利用線路資源,解決交通瓶頸問題,該城市制定了票價策略: 1. 每條線路可以單獨購票,票價不等。 2. 允許購買某些兩條可換乘的線路的聯票。聯票價格低於分別購票。 單線票價和聯合票價如 price.txt 所示。 線1 180 ..... 線13 114 線1,線2 350 線1,線10 390 ..... 每行數據表示一種票價 線名與票價間用空格分開。如果是聯票,線名間用逗號分開。 聯票只能包含兩條可換乘的線路。 現在的問題是:根據這些已知的數據,計算從A站到B站最小花費和可行的換乘方案。 比如,對於本題目給出的示例數據 如果用戶輸入: 五棵松,奧體中心 程序應該輸出: -(線1,線10)-線8 = 565 如果用戶輸入: 五棵松,霍營 程序應該輸出: -線1-(線4,線13) = 440 可以看出,用戶輸入的數據是:起始站,終到站,用逗號分開。 程序輸出了購票方案,在括號中的表示聯票,短橫線(-)用來分開乘車次序。 等號后輸出的是該方案的花費數值。 請編程解決上述問題。 注意: 1. 我們測試您的程序時,所用數據與題目中的示例數據不同,但格式完全一樣。 2. 當多個方案有相同的最小花費,輸出任意一個方案即可。 要求考生把所有類寫在一個文件中。 調試好后,存入與考生文件夾下對應題號的“解答.txt”中即可。 相關的工程文件不要拷入。請不要使用package語句。
對於此題,重點在於文本文件中信息的讀取,並選擇合適的數據結構來處理分類,好復雜的感覺,又看到相關備注,說明:此題類型在第四屆以后便不再用這種形式來出題,所以就簡單的看了一下網友的代碼,沒有自己上機實現。
Java版:藍橋杯-地鐵換乘
來自網友的C語言版:
1 #include<iostream> 2 using namespace std; 3 #define LEN 50 4 typedef struct stations{ 5 char name[20]; 6 int len; 7 int roads[50]; 8 struct stations *left; 9 struct stations *right; 10 }Stations; 11 12 typedef struct etree{ 13 int value; 14 int roadNum; 15 struct etree *father; 16 int childnum; 17 }ETree; 18 19 typedef struct queue{ 20 ETree *tie; 21 struct queue *next; 22 }Queue; 23 24 void pushQueue(Queue &head, ETree *&etree){ 25 Queue *p=head.next,*q=&head; 26 while(p!=NULL && (p->tie->value<etree->value)){ 27 q=p; 28 p=p->next; 29 } 30 q->next=(Queue*)malloc(sizeof(Queue)); 31 q->next->tie=etree; 32 q->next->next=p; 33 } 34 void freeEtree(ETree *q){ 35 ETree *p; 36 while(q->childnum==0){ 37 p=q; 38 q=q->father; 39 free(p); 40 if(q!=NULL) 41 q->childnum--; 42 else 43 break; 44 } 45 } 46 47 void freeAll(Stations *&head){ 48 if (head!=NULL){ 49 freeAll(head->left); 50 freeAll(head->right); 51 free(head); 52 } 53 } 54 55 void showBest(ETree *h,int price[][LEN],char roadName[][20],int roadNum){ 56 if(h!=NULL){ 57 if (h->faher==NULL){ 58 printf("%s",roadName[h->roadNum]); 59 } 60 else{ 61 int j; 62 j=h->roadNum; 63 if (h->value==(price[j][j]+h->father->value)){ 64 showBest(h->father,price,roadName,roadNum); 65 if (price[j][roadNum]){ 66 printf("-(%s,%s)",roadName[j],roadName[price[j][roadNum]-1]); 67 68 } 69 else 70 printf("-%s",roadName[j]); 71 } 72 else{ 73 showBest(h->father->father,price,roadNme,roadNum); 74 printf("-(%s,%s)",roadName[h->father->roadNum],roadName[j]); 75 } 76 } 77 } 78 } 79 80 inline int compares(char s1[],int n1,chr s2[],int n2){ 81 if (n1!=n2) 82 return n1-n2; 83 return strcmp(s1,s2); 84 } 85 boll findStation(Stations* &head,Stations* &p,char s[]){ 86 int len=strlen(s); 87 int t; 88 Stations q; 89 p=head; 90 while (n!=NULL){ 91 q=p; 92 t=compares(s,len,p->name,p->len); 93 if (t<0) 94 p=p->left; 95 else 96 retrn true; 97 } 98 p=q; 99 return false; 100 } 101 102 void insert(Stations* &head,char s[],int road,int price[][LEN]{ 103 Stations *p,*q; 104 int t; 105 t=strlen(s); 106 if(s[t-1]=='\n') 107 s[t-1]='\0'; 108 if(head==NULL){ 109 p=(Stations *)malloc(sizeof(Stations)); 110 p->left=NULL; 111 p->rght=NULL; 112 strcpy(p->name,s); 113 p->len=strlen(s); 114 p->road[0]=1; 115 p->road[1]read; 116 head=p; 117 } 118 else{ 119 if (findStation(head,p,s)){ 120 p->roads[0]++; 121 t=p->roads[0]; 122 p->roads[t]=road; 123 for(t--;t>0,t--){ 124 price[p->road[t]][road]=-1; 125 price[road][p->road[t]]=-1; 126 } 127 } 128 else{ 129 q=p; 130 p=(Stations *)malloc(sizeof(Stations)); 131 p->left=NULL; 132 p->right=NULL; 133 strcpy(p->name,s); 134 p->len=strlen(s); 135 p->road[0]=1; 136 p->road[1]=road; 137 t=compares(s,p->len,q->name,q->len); 138 if(t<0) 139 q->left=p; 140 else 141 q->right=p; 142 } 143 } 144 } 145 146 int GetRoadNum(char *r,char roadName[][20],int road Num){ 147 for (int i=0;i<roadNum;i++) 148 if (strcmp(roadName[i],r)==0) 149 return i; 150 return 0; 151 } 152 153 void main() 154 { 155 //[roadnum][roadnum+1] 156 int price[LEN][LEN]={0}; 157 char roadName[LEN][20]; 158 int i,j,k,t; 159 char line[20]; 160 int roadNum; 161 Stations *head=NULL; 162 FILE *fp; 163 if((fp=fopen("stations.xt","r"))==NULL){ 164 printf("找不到stations文件\n"); 165 return; 166 } 167 roadNum=0; 168 while(!feof(fp)){ 169 fscanf(fp,"%s%*c",roadName[roadNum]); 170 fgets(line,19,fp); 171 while(!feof(fp)&&line[0]!='\n'){ 172 insert(head,line,roadNum,price); 173 fgets(line,19,fp); 174 } 175 roadNum++; 176 } 177 roadNum++; 178 } 179 insert(head,line,roadNum-1,price); 180 fclose(fp); 181 if ((fp=fopen("price.txt","r"))==NULL){ 182 printf("找不到price文件"); 183 } 184 while (!feof(fp)){ 185 fscanf(fp,"%s,line); 186 fscanf(fp,"%d",&k); 187 for(t=0;line[t]!='\0'&&line[t]!=",";t++); 188 if (line[t]==','){ 189 line[t]='\0'; 190 i=GetRoadNum(line,roadName,roadNum); 191 j=GetRoadNum(line+t+1,roadName,roadNm); 192 price[i][j]=k; 193 price[j][i]=k; 194 if (price[i][i]>k){ 195 price[i][roadNum]=j+1; 196 } 197 if (price[j][j]>k){ 198 price[j][j]=k; 199 price[j]roadNum]=i+1; 200 } 201 } 202 else{ 203 i=GetRoadNum(line,roadName,roadNum); 204 price[i][i]=k; 205 } 206 } 207 208 fclose(fp); 209 210 char starts[20]={"五棵松"},ends[20]="奧體中心"}; 211 Stations *sroad,*eroad; 212 Queue Qhead, *h; 213 Etree *p,*q; 214 while(true){ 215 char Flag[LEN]={0};//為-1表示目標,為0表示尚未發生過擴展 216 Qhead.next=NULL; 217 Qhead.tie=NULL; 218 scanf("%[^,\n]s",starts); 219 if (getchar()!=',') 220 break; 221 scanf("%[^\n]s",ends); 222 getchar(); 223 if (!findStation(head,sroad,starts)){ 224 printf("未找到%s的匹配項\n",starts); 225 continue; 226 } 227 if (!findStation(head,eroad,ends)){ 228 printf("未找到%s的匹配項\n",ends); 229 continue; 230 } 231 for (i=1;i<=sroad->roads[0];i++){ 232 p=(ETree*)malloc(sizeof(ETree)); 233 p->father=NULL; 234 p->childnum=0; 235 p->roadNum=sroad->roads[i]; 236 p->value=price[p->roadum][p->roadNum]; 237 pushQueue(Qhead,p); 238 } 239 for (i=1;i<=eroad->roads[0];i++){ 240 Flag[eroad->roads[i]]=-1; 241 } 242 while(Qhead.next!=NULL){ 243 h=Qhead.next; 244 q=h->tie; 245 if (Flag[q->roadNum]==-1){ 246 break; 247 } 248 Qhuad.next=Qhead.next->next; 249 i=q->roadNum; 250 if (Flag[i]!=1){ 251 for(j=0;j<roadNum;j++){ 252 if (price[i][j]){ 253 q->childnum++; 254 p=(ETree*)malloc(sizeof(ETree)); 255 p->father=q; 256 p->childnum=0; 257 p->roadNum=j; 258 k=price[j][j]>0){ 259 if(price[i][j]>0){ 260 if(q->father!=NULL) 261 t=price[i][j]+q->father->value; 262 else 263 t=price[i][j]; 264 if (k>t) 265 k=t; 266 } 267 p->value=k; 268 pushQueue(Qhead,p); 269 } 270 } 271 Flag[i]=1; 272 } 273 freeETree(h->tie); 274 free(h); 275 } 276 if (Qhead.next!=NULL){ 277 showBest(q,price,roadName,roadNum); 278 printf("=%d\n",q->value); 279 } 280 else 281 printf("此路不通\n"); 282 for(;Qhead.next!=NULL;){ 283 h=Qead.next; 284 Qhead.nexQhead.next->next; 285 freeETree(h->tie); 286 free(h); 287 } 288 } 289 freeAll(head); 290 }
試題5
BMP是常見的圖像存儲格式。 如果用來存黑白圖像(顏色深度=1),則其信息比較容易讀取。 與之相關的數據: (以下偏移均是從文件頭開始) 偏移:10字節, 長度4字節: 圖像數據真正開始的位置。 偏移:18字節, 長度4字節: 位圖的寬度,單位是像素。 偏移:22字節, 長度4字節: 位圖的高度,單位是像素。 從圖像數據開始處,每個像素用1個二進制位表示。 從圖片的底行開始,一行一行向上存儲。 Windows規定圖像文件中一個掃描行所占的字節數必須是4字節的倍數, 不足的位均以 0 填充。例如,圖片寬度為45像素,實際上每行會占用 8個字節。 可以通過Windows自帶的畫圖工具生成和編輯二進制圖像。 需要在“屬性”中選擇“黑白”,指定為二值圖像。 可能需要通過 查看 | 縮放 | 自定義... 把圖像變大比例一些, 更易於操作。 圖像的左下角為圖像數據的開始位置。白色對應1,黑色對應0 我們可以定義:兩個點距離如果小於2個像素,則認為這兩個點連通。 也就是說:以一個點為中心的九宮格中,圍繞它的8個點與它都是連通的。 如:t1.bmp 所示,左下角的點組成一個連通的群體; 而右上角的點都是孤立的。 in.bmp t1.bmp 程序的目標是:根據給定的黑白位圖,分析出所有獨立連通的群體, 輸出每個連通群體的面積。所謂面積,就是它含有的像素的個數。 輸入數據固定存在in.bmp中。 如示例的in.bmp, 程序應該輸出: 12 81 52 133 該輸出表示:共有4個連通群體。 輸出的連通體面積間的順序可以隨意。 請編程解決上述問題。 我們測試程序的時候,會使用不同的in.bmp文件。 要求考生把所有類寫在一個文件中。 調試好后,存入與考生文件夾下對應題號的“解答.txt”中即可。 相關的工程文件不要拷入。請不要使用package語句。
圖 in.bmp
圖 t1.bmp
這題要讀入圖片文件數據,感覺頭大啊,此前做的題,幾乎沒有遇到要讀取文件中的數據,而現在竟然還碰到了讀取圖片的數據,看到此題的核心:即使用DFS求取連通圖的問題,並且返回每一個連通圖中包含的頂點個數,但是對於此題處理讀取數據的問題,就沒有仔細去探究,下面貼出一段網友的C語言代碼,以作參考:
1 include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 #include<string.h> 5 6 void main(){ 7 int i,j,k,m; 8 int width,height,start,world; 9 int *bmp,*Lcount; 10 bool *Lflag; 11 FILE *fp; 12 if((fp=fopen("in1.bmp","rb"))==NULL){ 13 printf("文件打開失敗"); 14 return; 15 } 16 fseek(fp,10L,0); 17 fscanf(fp,"%4c",&start); // 4c表示該數據占4個字節 18 // printf("start = %d\n",start); 19 fseek(fp,18,0); 20 fscanf(fp,"%4c",&width); 21 // printf("width = %d\n",width); 22 fseek(fp,22,0); 23 fscanf(fp,"%4c",&height); 24 // printf("height = %d\n",height); 25 bmp = (int*)malloc((width+2)*sizeof(int)); 26 memset(bmp,0,(width+2)*sizeof(int)); 27 Lcount = (int*)malloc(width*sizeof(int)); 28 memset(Lcount,0,width*sizeof(int)); 29 Lflag = (bool*)malloc(width*sizeof(bool)); 30 memset(Lflag,0,width*sizeof(bool)); 31 Lcount--; 32 Lflag--; 33 fseek(fp,start,0); 34 world = ( width%32 ? width/32+1 : width/32 )*4; 35 int last,i1,i2,i3; 36 int eCount = 0 37 for(i=0 i<height i++ ){ 38 char c; 39 k=1; 40 last=0; 41 for(j=0 j<world j++){ 42 fscanf(fp,"%c",&c); 43 for(m = 7 m >= 0 && k<=width m-- ){ 44 if( !( 1<<m & c ) ){ 45 //printf("*"); 46 if(bmp[k]){ 47 last = bmp[k]; 48 Lcount[last]++; 49 Lflag[last] = true 50 } 51 else{ 52 i1 = last ? last : bmp[k-1] 53 i3 = bmp[k+1] 54 last = 0; 55 if( i1 || i3){ 56 if( i1 && i3 && ( i1 != i3 ) ){//確定需要連接 57 Lcount[i1] += Lcount[i3] 58 Lcount[i3]=0; 59 for(i2=1;i2<=width i2++){ 60 if(bmp[i2]==i3) 61 bmp[i2] = i1; 62 } 63 } 64 else{ 65 if(!i1) 66 i1=i3; 67 } 68 bmp[k] = i1 69 Lcount[i1]++; 70 Lflag[i1] = true 71 } 72 else{//插入 73 for(i2=1;Lcount[i2];i2++); 74 Lcount[i2]=1; 75 bmp[k] = i2 76 Lflag[i2] = true 77 } 78 } 79 } 80 else{ //printf(" "); 81 last = bmp[k] 82 bmp[k] = 0 83 } 84 k++; 85 } 86 } 87 //printf("\n"); 88 for(i2=1;i2<=width;i2++){ 89 if(Lcount[i2] && !Lflag[i2] ){ 90 printf("%d\n",Lcount[i2]); 91 Lcount[i2] = 0 92 eCount++; 93 } 94 Lflag[i2]=false; 95 } 96 } 97 fclose(fp); 98 free(Lflag+1); 99 free(Lcount+1); 100 free(bmp); 101 printf("count=%d\n",eCount); 102 }