第二届:
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;
}
答案: n==0 f(n-i*i,a,idx+1)==1
2、加密
2. 加密
在对文本进行简单加密的时候,可以选择用一个n位的二进制数,对原文进行异或运算。
解密的方法就是再执行一次同样的操作。
加密过程中n位二进制数会循环使用。并且其长度也可能不是8的整数倍。
下面的代码演示了如何实现该功能。
请仔细阅读,填写空缺的代码(下划线部分)。
注意:请把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
直接写在题面中不能得分。
void f(char* buf, unsigned char* uckey, int n)
{
int i;
for(i=0; i<n; i++)
buf[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);// 密匙串需要按位的形式循环拼入 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] = (uckey[i / 8] << 1) | 0x01; (每一个字符类型8个字节,由于位运算单位为byte所以*8对每一位都赋值(该操作先向左移位,再在尾部字节加1))
uckey[i / 8] = uckey[i / 8] << 1; (直接左移一位)
uckey[i/8] &= ~((unsigned char)0x80 >> (i%8)); //标准答案
uckey[i/8] |= (unsigned char)0x80 >> (i%8); //标准答案
详细用法:http://blog.csdn.net/u014665013/article/details/45672015
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。
大数肯定不行,以后再改
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <string> #include <cmath> #define INF 0x3f3f3f3f #define Maxsize 100 using namespace std; long long gcd(long long a,long long b) { if(b==0) return a; long long t=a%b; while(t) { a=b; b=t; t=a%b; } return b; } int main(long long argc, char* argv[]) { long long n; while(cin>>n){ long long temp = 1; for(long long i=1;i<=n;i++){ temp=i/gcd(temp,i)*temp; } cout<<temp; } return 0; }
第三届
1.【结果填空】 (满分5分)
1949年的国庆节(10月1日)是星期六。
今年(2012)的国庆节是星期一。
那么,从建国到现在,有几次国庆节正好是星期日呢?
只要答案,不限手段!
可以用windows日历,windows计算器,Excel公式,。。。。。
当然,也可以编程!
不要求写出具体是哪些年,只要一个数目!
千万不要提交源代码!
答案不要写在这里,写在“解答.txt”中
答案:9
3.
【代码填空】(满分16分) 某工业监控设备不断发回采样数据。每个数据是一个整数(0到1000之间)。各个数据间用空白字符(空格,TAB或回车换行)分隔。这些数据以文本形 式被存储在文件中。 因为大多数时候,相邻的采样间隔数据是相同的,可以利用这个特征做数据的压缩存储。其方法是:对n(n>1)个连续相同的数字只记录n和该数字本 身;对m(m>0)个连续不重复的数字,则记录 m*-1 和这些数字本身(之所以用负数,是为了与第一种情况区分,便于解压缩)。 例如:采样数字: 12 34 34 25 25 25 25 11 15 17 28 14 22 22 22 13 则根据上述规则变化后: -1 12 2 34 4 25 -5 11 15 17 28 14 3 22 -1 13 下面的程序实现了这个功能。请仔细阅读分析代码,填写空白的部分。 void pop(int s, int* buf, int c, FILE* fp) { int i; if(s) { fprintf(fp, "%d %d ", c, *buf); } else { fprintf(fp, "%d ", -c); for(i=0; i<c; i++) { fprintf(fp, "%d ", buf[i]); } } } void dopack(FILE* r, FILE* w) { int buf[BUF_N]; int pos = 0; // 下一个数字在buf中将要存放的位置 int c = 0; // 当前段已读入的整数个数 int pst; int cst; while(fscanf(r, "%d", buf+pos)==1) { if(c==0) { c = pos = 1; continue; } if(c==1) { pst = buf[0] == buf[1]; pos = pos + 1 - pst; c = 2; continue; } cst = buf[pos-1] == buf[pos]; if(pst && !cst) { pop(pst, buf, c, w); buf[0] = buf[1]; c = pos = 1; pst = cst; } else if(!pst && cst || pos == BUF_N-1) { pop(pst, buf, c-1, w); buf[0] = buf[pos-1]; c = 2; if(!cst) { buf[1] = buf[pos]; pos = 2; } else { pos = 1; pst = ______________; // 填空1 } } else { c++; if(!pst) pos++; } } // while if(c>0) _____________________________; // 填空2 } void main() { FILE* rfp; FILE* wfp; if((rfp=fopen(RFILE, "r")) == NULL) { printf("can not open %s! ", RFILE); exit(1); } if((wfp=fopen(WFILE, "w")) == NULL) { printf("can not open %s! ", WFILE); fclose(rfp); exit(2); } dopack(rfp, wfp); fclose(wfp); fclose(rfp); } 【注意】 只填写缺少的部分,不要抄写已有的代码。 所填写代码不超过1条语句(句中不会含有分号) 所填代码长度不超过256个字符。 答案写在“解答.txt”中,不要写在这里!
技巧说明:在做代码填空题的时候,还是尽量看懂一步就做一下注释,这样最后思路就会清晰很多,一下子没有做出来的之后看也是比较方便的。(这一次就是这样做出来的)
答案:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<cmath> #define INF f0x3f3f3f3f #define BUF_N 1000 using namespace std; void pop(int s,int *buf,int c,FILE *fp) { int i; if(s) fprintf(fp,"%d %d ",c,*buf); else { fprintf(fp,"%d ",-c); for(i=0; i<c; i++) fprintf(fp,"%d ",buf[i]); } } void dopack(FILE *r,FILE *w) { int buf[BUF_N]; int pos=0;//下一个数字在buf中将要存放的位置 int c=0;//当前段已读入的整数个数 int pst;///确定符号 int cst; while(fscanf(r,"%d",buf+pos)==1) { if(c==0) { c=pos=1; continue; } if(c==1) { pst= ( buf[0]==buf[1] ) ; ///pst记录前两个是否相同 pos=pos+1-pst; ///前两个不相同时 pos= 2 c=2; continue; } cst = ( buf[pos-1]==buf[pos] );///第二个和第三个相同 if( pst&&!cst ) ///前边两个相同,后面的出现不相同 { pop(pst,buf,c,w); buf[0]=buf[1]; c=pos=1; pst=cst; } else if( !pst&&cst || pos==BUF_N-1 ) ///前两个不相同 第二个第三个相同 || 到最后 { pop(pst,buf,c-1,w); buf[0]=buf[pos-1]; c=2; if(!cst) ///文件最后 { buf[1]=buf[pos]; pos=2; } else ///前两个不相同 第二个第三个相同 { pos=1; pst=1 ;//填空1 } } else ///前后都相同,前后都不相同 { c++; if(!pst)pos++; } }//while if(c>0) pop(pst,buf,c,w); //填空2 } int main() { FILE *rfp; FILE *wfp; if((rfp=fopen("D:\in.txt","r"))==NULL)//从文件中输入 rfp指针返回NULL则是没有打开,下面同理,路径可以有中文 { printf("cannot open1! "); exit(1); } if((wfp=fopen("D:\out.txt","w"))==NULL) { printf("cannot open2! "); fclose(rfp); exit(2); } dopack(rfp,wfp); fclose(wfp); fclose(rfp); return 0; }
3.
4.
5.
详见网址:http://blog.csdn.net/u014665013/article/details/45848277