Sweety

Practice makes perfect

导航

蓝桥杯决赛集锦

Posted on 2015-05-10 19:10  蓝空  阅读(187)  评论(0编辑  收藏  举报

第二届:

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;
}

答案: 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\n", 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!\n", RFILE);
exit(1);
}

if((wfp=fopen(WFILE, "w")) == NULL)
{
printf("can not open %s!\n", 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!\n");
        exit(1);
    }

    if((wfp=fopen("D:\\out.txt","w"))==NULL)
    {
        printf("cannot open2!\n");
        fclose(rfp);
        exit(2);
    }

    dopack(rfp,wfp);

    fclose(wfp);
    fclose(rfp);
    return 0;
}







3.



4.


5.

详见网址:http://blog.csdn.net/u014665013/article/details/45848277