1.回文日
2011年11月02日是一个回文日:2011 1102,请列出本世纪还有多少个回文日?
当年份确定后,如2015年,就看20155102能否构成一个合法的日期,其中51部分是月,02部分是日。显然,由2015就不能得出一个回文日。
再如,当年份取2090年时,20900902,由2090可以构造出一个回文日来。
用年份循环并判断,而不是罗列所有的日期,显然效率上更好。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int year,month,day,date,y;
int is_cycle;//用于标识判断结果
int count=0;
for(year=2015;year<2100;year++)
{
is_cycle=0;
month=year%100;//若原月份前两位是回文日,原年份后两位对应月
month=month/10+month%10*10;//把月倒过来为真正月份
day=year/100;//若是回文日,原年份前两位对应日
day=day/10+day%10*10;//把日倒过来为真正日
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(day<=31){
is_cycle=1;
}
break;
case 4:
case 6:
case 9:
case 11:
if(day<=30){
is_cycle=1;
}
break;
case 2:
if((year%4==0&&year%100!=0)||year%400==0){//闰年
if(day<=29){
is_cycle=1;
}
}
else{
if(day<=28){
is_cycle=1;
}
}
break;
default:
continue;
}
y=year;
if(is_cycle){
date=y;
while(y>0){
date=date*10+y%10;
y/=10;
}
printf("%d\n",date);
count++;
}
}
printf("共有%d个回文日.\n",count);
return 0;
}
2.确定等式
有等式[※×(※3+※)]^2=8※※9,其中※处为1个数字,滴上了墨水无法辨认。请编程找出※表示哪个数字。
代码:【遍历】
#include <stdio.h>
#include <math.h>
int main()
{
int a,b,c,temp,left;
for(a=1;a<=9;a++){
for(b=1;b<=9;b++){
for(c=0;c<=9;c++){
temp=a*((b*10+3)+c);
left=pow(temp,2);
if(left/1000==8&&left%10==9){
printf("%d %d %d %d %d\n",a,b,c,left/100-left/1000*10,left/10-left/100*10);
}
}
}
}
return 0;
}
需要注意的是在调用pow函数时,要求参数类型为float,返回值类型也为float,因此容易造成精度损失。
单步执行时当temp=13,15,20,21,22,23..时(起始13)对应的left都少1,而其他数(14,16,17,18,...)都正常。
所以应将
left=pow(temp,2);
改为 :
left=temp*temp;
//或者
left=(int)(0.1+pow(temp,2));
错误的运行:
正确运行:
3.fflush(stdin):清除键盘缓存区
(缓存区:在输入输出时,系统分配一段内存区域,将输入输出的内容放在这片区域)
fflush:函数名;stdin代表标准输入(键盘)
有如下程序常用于重复性工作:
#include<stdio.h>
void dosomething(int *p);
int main( )
{
char choice='y';
int n=0;
while(choice!='N' && choice!='n')
{
dosomething(&n);
printf("按 N 退出,其他键继续....");
scanf("%c", &choice); //用choice=getchar();也一样
}
return 0;
}
void dosomething(int *p) //完成特定的业务
{
*p+=1; //本例中传地址, *p即n
printf("第%d次完成业务!\n", *p);
}
输入:666<回车>
发现运行异常。这是因为缓存区中保存了666'\n'[回车字符],所以第三次时直接的choice用缓存区中的第二个6,第四次choice用缓存区中的第三个6,第五次choice用缓存区中的'\n',以至于多出来了:
正确的源代码应该在输入前先清除缓存区:
#include<stdio.h>
void dosomething(int *p);
int main( )
{
char choice='y';
int n=0;
while(choice!='N' && choice!='n')
{
dosomething(&n);
printf("按 N 退出,其他键继续....");
fflush(stdin);//读入字符前,常要清空“输入缓存区”
scanf("%c", &choice); //用choice=getchar();也一样
}
return 0;
}
void dosomething(int *p) //完成特定的业务
{
*p+=1; //本例中传地址, *p即n
printf("第%d次完成业务!\n", *p);
}
4.将十进制数转换成n进制数
#include <stdio.h>
#include <stdlib.h>
//除以n取余数保存在数组中,然后将数组从后往前输出,因为后面是高位
int main()
{
int n,b,i=0,j,a[20];
scanf("%d",&n);
scanf("%d",&b);
while(b)
{
a[i++]=b%n;
b/=n;
}
i--;
for(j=i;j>=0;j--)
{
printf("%d",a[j]);
}
printf("\n");
return 0;
}
运行结果:
5.二分法解方程
二分法是在计算机科学中很重要的一种方法,用于查找产生二分查找算法,还可以用在很多场合。
可以用二分法解方程。
对于区间[a,b]上连续不断且f(a)·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。
假设要求方程f(x)=0的解,给定精确度ξ。其算法是:
- 1 确定区间[a,b],验证f(a)·f(b)<0
- 2 求区间(a,b)的中点c
- 3 判断
(2) 若f(c)·f(b)<0,则令a=c.
- 4 判断f(c)是否达到精确度ξ:即若┃f(c)┃<ξ,则x=c就是使f(x)接近零点的近似值,否则重复2-4.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double f(double x);
int main()
{
double a,b,c;
do{
printf("请输入一个范围:");
scanf("%lf %lf",&a,&b);
}while(f(a)*f(b)>0);
printf("该方程在%lf-%lf之间有一解为",a,b);
do{
c=(a+b)/2;
if(f(a)*f(c)<0)
b=c;
else
a=c;
}while(fabs(f(c))>1e-5);
printf("%lf\n",c);
return 0;
}
double f(double x)
{
return (3*x*x*x-5*x*x+3*x-6);
}
运行: