前言:
备赛蓝桥杯,大学电子设计大赛,C语言提高,算法准备,定位大厂刷题,所以每天一练,不是很适合新手,适合长期规划有一定基础的同学跟上,每日文档由三部分组成,基础题(适合备赛国二),趣味题(适合有兴趣的同学),经典算法题(适合更高要求)组成。当然本意是记录自己训练的过程,基础题基本能做出来,能给自己一个正面回馈,趣味题可以培养兴趣,经典算法题用于真正来训练自己,开眼见长见识,在遇到困难的问题有更好的解决办法,最关键是每天三个题充分利用了零碎时间,细水才能长流,共勉坚持!!!!
基础题:
【程序28】 题目:输出9*9口诀。
1.程序分析:
分行与列考虑,共9行9列,i控制行,j控制列。
2.程序源代码:
#include "stdio.h"
main()
{
int i,j,result;
printf("\n");
for (i=1;i<10;i++)
{ for(j=1;j<10;j++)
{
result=i*j;
printf("%d*%d=%-3d",i,j,result);/*-3d表示左对齐,占3位*/
}
printf("\n");/*每一行后换行*/
}
}
趣味题:
28.回文数
打印所有不超过n(取n<256) 的其平方具有对称性质的数(也称回文数)。
*问题分析与算法设计
对于要判断的数n,计算出其平方后(存于a),将a的每一位进行分解,再按a的从低到高的顺序将其恢复成一个数k(如n=13,则a=169且k=961),若a等于k则可判定n为回亠数。
*程序说明与注释
原程序好像有错,而且比较费解,现基于原程序修改如下(如果读者还发现错误请提出):
#include<stdio.h>
int main(void)
{
int m[16],n,i,t,count=0;
long unsigned a,k;
printf("No. number it's square(palindrome)\n");
for(n=1;n<256;n++) /*穷举n的取值范围*/
{
k=0;t=1;a=n*n; /*计算n的平方*/
for(i=0;a!=0;i++) /*从低到高分解数a的每一位存于数组m[0]~m[16]*/
{
m[i]=a%10;//这个是取得a的个位,整个循环合起来就可以取得各个位
a/=10;
}
int j=0;
for(i–;j<i;j++,i–)//因为n的平方的各个位都存在数组中了,下面判断是不是对称
if(m[j]!=m[i])break;//只要有一位不是对称,那就说明不是对称,就可以退出了
//所有的位都对称就说明是对称了,这样就可以打印出结果了
if(j>=i)printf("%2d%10d%10d\n",++count,n,n*n);
}
return 0;
}
运行结果
No. number it’s square(palindrome)
1 1 1
2 2 4
3 3 9
4 11 121
5 22 484
6 26 676
7 101 10201
8 111 12321
9 121 14641
10 202 40804
11 212 44944
//下面程序是原来的,有错,而且费解
#include<stdio.h>
int main(void)
{
int m[16],n,i,t,count=0;
long unsigned a,k;
printf(“No. number it’s square(palindrome)\n”);
for(n=1;n<256;n++) /穷举n的取值范围/
{
k=0;t=1;a=nn; /计算n的平方/
for(i=1;a!=0;i++) /从低到高分解数a的每一位存于数组m[1]~m[16]/
{
m[i]=a%10;//安安注:这个是取得a的个位,整个循环合起来就可以取得各个位,并存于数组中,为了是下面判断是不是对称
a/=10;
}
for(;i>1;i–)
{
k+=m[i-1]t;
t=10;
}
if(k==nn)
printf(“%2d%10d%10d\n”,++count,n,nn);
}
return 0;
}
*运行结果
No. number it’s square(palindrome)
1 1 1
2 2 4
3 3 9
4 11 121
5 22 484
6 26 676
7 101 10201
8 111 12321
9 121 14641
经典算法题:
28.格雷码(Gray Code)
说明
Gray Code是一个数列集合,每个数使用二进位来表示,假设使用n位元来表示每个数好了,任两个数之间只有一个位元值不同,例如以下为3位元的Gray Code:
000 001 011 010 110 111 101 100
由定义可以知道,Gray Code的顺序并不是唯一的,例如将上面的数列反过来写,也是一组Gray Code:
100 101 111 110 010 011 001 000
Gray Code是由贝尔实验室的Frank Gray在1940年代提出的,用来在使用PCM(Pusle Code Modulation)方法传送讯号时避免出错,并于1953年三月十七日取得美国专利。
解法
由于Gray Code相邻两数之间只改变一个位元,所以可观 察Gray Code从1变0或从0变1时的位置,假设有4位元的Gray Code如下:
0000 0001 0011 0010 0110 0111 0101 0100
1100 1101 1111 1110 1010 1011 1001 1000
观察奇数项的变化时,我们发现无论它是第几个Gray Code,永远只改变最右边的位元,如果是1就改为0,如果是0就改为1。
观察偶数项的变化时,我们发现所改变的位元,是由右边算来第一个1的左边位元。
以上两个变化规则是固定的,无论位元数为何;所以只要判断位元的位置是奇数还是偶数,就可以决定要改变哪一个位元的值,为了程式撰写方便,将阵列索引 0当作最右边的值,而在列印结果时,是由索引数字大的开始反向列印。
将2位元的Gray Code当作平面座标来看,可以构成一个四边形,您可以发现从任一顶点出发,绕四边形周长绕一圈,所经过的顶点座标就是一组Gray Code,所以您可以得到四组Gray Code。
同样的将3位元的Gray Code当作平面座标来看的话,可以构成一个正立方体,如果您可以从任一顶点出发,将所有的边长走过,并不重复经过顶点的话,所经过的顶点座标顺序之组合也就是一组Gray Code。
#include <stdio.h>
#include <stdlib.h>
#define MAXBIT 20
#define TRUE 1
#define CHANGE_BIT(x) x = ((x) == '0' ? '1' : '0')
#define NEXT(x) x = (1 - (x))
int main(void) {
char digit[MAXBIT];
int i, bits, odd;
printf("输入位元数:");
scanf("%d", &bits);
for(i = 0; i < bits; i++) {
digit[i] = '0';
printf("0");
}
printf("\n");
odd = TRUE;
while(1) {
if(odd)
CHANGE_BIT(digit[0]);
else {
// 计算第一个1的位置
for(i = 0; i < bits && digit[i] == '0'; i++) ;
if(i == bits - 1) // 最后一个Gray Code
break;
CHANGE_BIT(digit[i+1]);
}
for(i = bits - 1; i >= 0; i--)
printf("%c", digit[i]);
printf("\n");
NEXT(odd);
}
return 0;
}
后续
有更优秀的解法和更优秀的训练题评论区留言,多交流!!!