前言:
点开这篇文章的你是不是也和我一样在备战蓝桥杯竞赛呢?或者抱着学习的态度浏览,亦或刷文章…无论怎样,请阅读到底,绝对不会令大家失望的。(滑稽脸)
博主花了一天时间做完题目,写博客的时候才发现没有彻底弄懂,会做的不一定能很好的表达出来或者讲出来,于是又去参考资料,彻底弄懂后,代码又重新过了一遍,才敢码字开始写博客。因为我知道,学习是一件严谨的事,我不想因为我文章中的某个错误而误导了别人。(严肃脸)
好了,fei话不多说,进入正题吧!
————————————————————
文章目录:
一:Fibonacci数列求余问题
二:神奇的01字串
三:字母图形的魅力
四:水仙花数
五:特殊的回文数
一:Fibonacci数列的求余问题
问题描述:
*Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
输入格式:
输入包含一个整数n。
输出格式:
输出一行,包含一个整数,表示Fn除以10007的余数。
说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。
数据规模与约定
1 <= n <= 1,000,000。
*
代码如下:
#include"stdio.h"
#define N 10007
int main()
{
int f1=1,f2=1,temp;
long int i,n;
scanf("%ld",&n);
for(i=1;i<n;i++)
{
temp=f2;
f2=(f1+f2)%N;
f1=temp;
}
printf("%d\n",f1);
return 0;
}
调试结果:
注释:
主要思路:因为本题要求求出fn对10007的余数,故将余数存入f2,引入辅助变量temp来把上一个f2的值赋给下一次循环中的f1。不断循环,直到循环结束,因为结束前执行的最后一个语句为f1=temp,而此时temp是上一个循环中的f2即循环结束时求的最后一次余数,故将f1或者temp输出即为所求。
读者可能有
(1):为什么循环从1开始而不是0?
因为本题要求Fn对10007的余数,而f2用来存放该余数,在循环开始前,f2已经被初始化为1,即相当于求了一次f2所以在循环体中不用再求第一次的f2,所有循环次数应为n-1次,即循环变量从1开始。
(2):为什么最后以f1的形式输出?以temp形式输出行吗?
因为循环结束前执行的最后一个语句为f1=temp,而此时temp是上一个循环中的f2即循环结束时求的最后一次余数,故将f1或者temp输出即为所求。
注意点:
本题数据规模与约定
1 <= n <= 1,000,000。
所以n和i都要定义为长整型,如果是int类型,数据会溢出输出一堆负数
————————————————————
二:神奇的01字串
问题描述:
对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:
00000
00001
00010
00011
00100
请按从小到大的顺序输出这32种01字串。
解析:
本题具有一定的迷惑性,我一开始的思路过程:定义一个32行5列的二维数组,找到数字间的规律依次赋值,再将二进制的01字串转换为十进制进行从小到大的排序,之后输出。可是,这是不是将问题复杂化了呢?
再观察:数列中所有的数字均是由0和1组成,而且这5位01串从右向左挨个赋值,所以可不可以定义5个循环变量来一个5重循环?每次循环将0和1遍历,从右向左的5位,对应从里向外的5重循环,依次赋值输出,这样也省了排序。因为数据规模n不大,所以法一就是纯纯的暴力美学!
代码如下:
方法一:
#include"stdio.h"
int main()
{
int a,b,c,d,e;
for(a=0;a<2;a++)
{
for(b=0;b<2;b++)
{
for(c=0;c<2;c++)
{
for(d=0;d<2;d++)
{
for(e=0;e<2;e++)
{
printf("%d%d%d%d%d\n",a,b,c,d,e);
}
}
}
}
}
return 0;
}
方法二:
观察发现者32行就是十进制数0,1,2,…,31转化为二进制再输出,并且是以五位的形式。那么可以定义一个大小为5的数组并初始化为0,然后十进制转二进制的时候逆序录入到数组中,然后转化完之后再正向输出,即可得到对应的五位的二进制数字。这个方法较于法一来说是优化的方法。
#include<stdio.h>
void Change(int x){
int ys,i,j=4;
int temp[5]={0,0,0,0,0};//初始化
while(x>0){
ys=x%2;
x=x/2;
temp[j--]=ys;//逆序录入
}
for(i=0;i<5;i++){
printf("%d",temp[i]);//正向输出
}
printf("\n");
}
int main(){
int i;
printf("00000\n");
for(i=1;i<32;i++)
Change(i);
return 0;
}
调试结果:
————————————————————
三:字母图形的魅力
问题描述:
利用字母可以组成一些美丽的图形,下面给出了一个例子:
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。
输入格式
输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。
输出格式
输出n行,每个m个字符,为你的图形。
数据规模与约定
1 <= n, m <= 26。
解析:
本题与“打印杨辉三角形”有异曲同工之妙。图形题,第一从特殊处着手,这是突破口。第二寻求图形、数字、字母间的内在规律将其抽象为一个数学公式用编程语言在程序中表达出来。
本题最突出的一个特点是第一行和第一列均是A,B,C,D,E,F,G…单调递增排列,所以可以先将特殊的处理一下,利用两个循环,单独对第一行和第一列的所有元素进行赋值。再观察发现:从第二行开始,每一行除了首列,每一列的字母都等于其所在位置上一行前一列的字母。发现这一核心点,本题就迎刃而解了!
代码如下:
#include"stdio.h"
int main()
{
int i,j,n,m,a[26][26];
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
a[i][0]='A'+i;
for(j=0;j<m;j++)
a[0][j]='A'+j;
for(i=1;i<n;i++)
for(j=1;j<m;j++)
a[i][j]=a[i-1][j-1];
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%c",a[i][j]);
}
printf("\n");
}
return 0;
}
调试结果:
图形题总结:要培养“由特殊到一般”的核心思想和发散性思维与提高多角度观察能力。
————————————————————
四:特殊的数字(水仙花数)
问题描述:
*153是一个非常特殊的数,它等于它的每位数字的立方和,
即153= 1 * 1 1+ * 5 * 5 * 5+ 3 * 3 * 3编程求所有满足这种条件的三位十进制数。
输出格式:
按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。
解析:
这是一道C语言教材上很经典的题目,这里我主要介绍两种思路:
(1)思路一:化零为整:因为要输出所有的三位十进制的水仙花数,所以可以采用三重循环,最外层进行数字1~9的遍历,因为要求是三位,百位上不能为0,其次内部两层循环进行数字0 ~9的遍历,在最内层的循环体内进行条件判断,符合的数字直接合成三位数输出。
(2)思路二:化整为零:利用一层循环for(i=100;i<1000;i++)进行所有三位数的遍历,循环体内部,将每一个三位数的各位数字分出来,再验证是否符合水仙花数的条件,符合直接输出此时的循环变量 i ,否则利用continue语句跳过本次循环继续进行下一次的循环。
思路一的代码如下:
#include"stdio.h"
int main()
{
int a,b,c;
for(a=1;a<=9;a++)
{
for(b=0;b<=9;b++)
{
for(c=0;c<=9;c++)
{
if(a*a*a+b*b*b+c*c*c==100*a+10*b+c)
printf("%d\n",100*a+10*b+c);
}
}
}
return 0;
}
调试结果:
思路二的代码:
#include"stdio.h"
int main()
{
int i,a,b,c;
for(i=100;i<1000;i++)
{
a=i/100;
b=i/10%10;
c=i%10;
if(a*a*a+b*b*b+c*c*c==i)
printf("%d\n",i);
else
continue;
}
return 0;
}
调试结果:
五:特殊的回文数
问题描述:
123321是一个非常特殊的数,它从左边读和从右边读是一样的。这类数字叫做“回文数”。
输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
输入格式:输入一行,包含一个正整数n。
输出格式:按从小到大的顺序输出满足条件的整数,每个整数占一行。
样例输入:
52
样例输出:
899998
989989
998899
数据规模和约定:
1<=n<=54。
解析:
主要思路:
以六位十进制数字为例,用一层循环对所有的六位数进行遍历,再利用除与取余的手段将该整数各位数剥离出来,用两层条件判断语句来判断是否符合既是回文数字,且各位数字之和等于所输入的数字n。将符合条件的数字存入数组array1[ ]中,用 j 来累加符合条件数字的总个数,便于下面作为实参传递给形参进行升序排列,最后输出即可。
五位十进制数字如法炮制,最后先输出所有符合条件的五位数,这样自然地省去了对符合条件的五位数与六位数进行排序的操作。
主要概括:
遍历所有—>各位剥离—>条件判断—>符合保存—>累加计数—>调用函数—>升序排列—>先后输出—>解决问题
代码如下:
#include"stdio.h"
int main()
{
void sort(int a[],int m);//自定义sort函数来实现排序功能
int n,a,b,c,d,e,f;//a,b,c,d,e,f分别用来存放该数字的各位数
int k,j=0,J=0,array1[100],array2[100];//定义两个足够大的数组来存放符合条件的数字,便于排序与输出
long int i,I;//由于要求符合条件的五位和六位十进制数字,所以要定义长整型变量,否则数据将溢出
scanf("%d",&n);
for(i=100000;i<1000000;i++)//对所有的六位十进制数字进行遍历
{
a=i/100000;
b=i/10000%10;
c=i/1000%10;//利用除与取余的手段分出各位数字
d=i/100%10;
e=i/10%10;
f=i%10;
if((a+b+c+d+e+f)==n)//判断是否符合“特殊的回文数”的条件
{
if(a==f&&b==e&&c==d)
{
array1[j]=i;
j++;//j相当于计数器,累计符合条件的六位十进制数字的个数,便于下面排序
}
}
}
for(I=10000;I<100000;I++)//输入符合条件的五位十进制数字与上 如法炮制
{
a=I/10000;
b=I/1000%10;
c=I/100%10;
d=I/10%10;
e=I%10;
if((a+b+c+d+e)==n)
{
if(a==e&&b==d)
{
array2[J]=I;
J++;
}
}
}
sort(array1,j);
sort(array2,J);
for(k=0;k<J;k++)//细节:因为最小的六位数肯定比最大的五位数大,所以这里先输出符合条件的五位十进制数
printf("%d\n",array2[k]);//这样很自然地省去了对五位数和六位数的排序
for(k=0;k<j;k++)
printf("%d\n",array1[k]);
return 0;
}
void sort(int a[],int m)//选择排序法
{
int i,j,k;
long int temp;
for(i=0;i<m-1;i++)
{
k=i;
for(j=i+1;j<m;j++)
{
if(a[j]<a[k])
k=j;
}
temp=a[i];a[i]=a[k];a[k]=temp;
}
}
调试结果:
————————————————————
结尾:
★原创不易★
如果这篇文章对你有些帮助与收获,可否点赞加关注呢?(害羞脸)
大家的支持与认可是我创作的不竭动力!
另外如果有疑问的话可在评论区评论,我尽量有空一一答复 ︿ ︿
————————————————————
最后和大家分享一段话:
这个世界非常多样,
自我实现的方式也绝不止哪一种。
我们每个人都不一样,
永远不要试图成为他人,
那是妄念。
我们唯一能做的,
就是看清自己并努力成为更好的自己,
这条路永远都不会错。
共勉!
————————————————————
我是Aricl.,期待你的关注!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/93515.html