前言:以下代码部分仅供参考,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 ", 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 ", 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]==' ') 107 s[t-1]='