C语言编程

1.舍罕王的失算
题目要求:舍罕是古印度的国王,据说他十分好玩,宰相达依尔为讨好国王,发明了现今的国际象棋献给国王。舍罕非常喜欢这项游戏,于是决定嘉奖达依尔,许诺可以满足达依尔提出的任何要求。达依尔指着舍罕王前面的棋盘提出要求:“陛下,请您按棋盘的格子上次我一点麦子吧,第1个小格赏我一粒麦子,第2个小格赏我两粒,第3个小格赏四粒,以后每一小格都比前一小格赏的麦粒数增加一倍,只要把棋盘上全部64个小格按这样的要求得到的麦粒都赏赐给我,我就心满意足了。”舍罕王听了达依尔的这个“小小的”要求,想就没想就满口答应了。
程序代码:
#include
#include
main()
{
int i;
double sum=0.0;
for(i=1;i<=64;i++)
sum+=pow(2,i-1);
printf("the summary is %g\n",sum);
}
程序说明:程序中定义sum为double类型是因为该题目的运算结果为一个20位十进制的大数,在C语言中的基本数据类型中,只有double类型和long double类型的数据可以容纳。
2.求两个数的最大公约数和最小公倍数。
题目要求:编写一个程序计算两个正整数的最大公约数和最小公倍数。
程序代码:
方法一:
#include
#include
main()
{
int a,b,r,temp,max,min;//定义从键盘输入的两个数与一个余数
printf("please input two numbers:\n");
scanf("%d,%d",&a,&b);
if(atemp=a;
a=b;
b=temp;
}
max=a;
min=b;
r=a%b;
while(r!=0)//求最大公约数
{
a=b;
b=r;
r=a%b;
}
printf("最大公约数为:%d\n",b);
//求最小公倍数
printf("最小公倍数为:%d\n",(max*min/b));
}
方法二:
一个数i为a和b的公共因数,那么一定满足a%i等于0,并且b%i等于0.所以,设计算法时只要从i=min(a,b)开始依次递减1,并逐一判断i是否为a和b的公共因数,得到的第一个公因数就是a和b的最大公因数。
一个数i为a和b的公共倍数,那么一定满足i%a等于0,并且i%b等于0.所以,设计算法时只要从i=max(a,b)开始依次加1,并逐一判断i是否为a和b的公共倍数,得到的第一个公倍数就是a和b的最大公倍数。
程序代码:
#include
#include
int gcd(int a,int b){//求最大公约数
int min;
if(a<0 || b<0)
return 0;
if(amin=a;
else min=b;//找到a,b中较小的一个数赋予min
while(min){
if(a%min==0 && b%min==0)//判断公因数
return min;//找到最大公约数返回
min--;//没找到最大公约数,min减1
}
return -1;
}
int icm(int a,int b){
int max;
if(a<0 || b<0)
return 0;
if(a>b)
max=a;
else max=b;
while(max){
if(max%a==0 && max%b==0)
return max;
max++;
}
return -1;
}
main()
{
int a,b;
printf("please input two numbers:\n");
scanf("%d,%d",&a,&b);
printf("the gcd of %

d and %d is %d\n",a,b,gcd(a,b));//输出最大公约数
printf("the icm of %d and %d is %d\n",a,b,icm(a,b));//输出最小公倍数
}
3.哥德巴赫猜想的近似值
题目要求:众所周知,哥德巴赫猜想的证明是一个世界性的数学难题。至今不能解决。我国著名数学家陈景润为哥德巴赫猜想的证明做出过杰出的贡献。
所为哥德巴赫猜想是说任何一个大于2的偶数都能表示为两个素数之和。应用计算机工具可以很快地在一定范围内验证哥德巴赫猜想的正确性。请编写一个C程序,验证指定范围内哥德巴赫猜想的正确性,也就是证明哥德巴赫猜想(因为不可能用计算机穷举出所有正偶数)
题目分析:可以应用枚举的方法列出指定范围内的每一个偶数,然后判断它是否满足哥德巴赫猜想的论断,一旦发现有不满足哥德巴赫猜想的数据,则可以跳出循环,并做出否定的结论;否则,如果集合内的数据都满足哥德巴赫猜想的论断,则可以说明在指定范围内,哥德巴赫猜想
是正确的。
这一过程的伪码算法为:
low 范围上界
high 范围下界
a<-low
repeat:
if a为偶数并且a>2 then
if a满足哥德巴赫猜想 then
输出一种结论
else
设置标志,跳出循环
endif
endif
a<-a+1
until a>high
if设置标志 then 哥德巴赫猜想不成立
else 在[low,high]内哥德巴赫猜想成立
一个正偶数a一定可以表示成为a/2中正整数相加的形式。这是因为a=a+(a-1);a=2+(a-2);a=3+(a-3);......;a=a/2-1+a/2+1;a=a/2+a/2;共a/2种。后面还有a/2-1种表示形式和前面a/2+1中表示形式相同,因此可以不予考虑。那么,在这a/2种正整数相加的形式中,只要存在一种形式a=i+j,其中i和j均为素数,则就可以断定该偶数a满足哥德巴赫猜想。因此,判断一个大于2的偶数a是否满足哥德巴赫猜想的伪码算法描述为:
i<-1
repeat:
if i是素数 and a-i也是素数 then
设置标志,跳出循环
endif
i<-i+1
until i>a/2
if 设置标志 then a满足哥德巴赫猜想
else a不满足哥德巴赫猜想
程序代码:
#include
#include
int isGoldbach(int a);
int TestfyGB_Guess(int low,int high);
int isPrime(int i);
main()
{
/*验证1~100以内的哥德巴赫猜想*/
printf("now testify Goldbach Guess in the range of 1~100\n");
if(TestfyGB_Guess(1,100))
printf("In the range of 100,Goldbach Guess is right.\n");
else printf("Goldbach Guess is wrong\n");
}
int TestfyGB_Guess(int low,int high){//在low和high之间验证哥德巴赫猜想
int i,j=0,flag=0;
for(i=low;i<=high;i++){
if(i%2==0 && i>2)
if(isGoldbach(i)){
j++;
if(j%5==0)
{
printf("\n");
j=0;
}
}
else{
flag=1;
break;
}
}
if(flag==1)
return 1;
else
return 0;
}
int isGoldbach(int a){//判断偶数是

否满足哥德巴赫猜想
int i,flag=0;
for(i=0;i<=a/2;i++)
if(isPrime(i) && isPrime(a-i)){
flag=1;
printf("%d=%d+%d",a,i,a-i);
break;
}
if(flag==1)
return 1;
else
return 0;

}
int isPrime(int i){//判断一个数是否为素数
int flag=1,n;
if(i==1)
flag=0;
for(n=2;nif(i%n==0){
flag=0;
break;
}
if(flag==1)
return 1;
else
return 0;
}
4.三色球问题
题目要求:有红、黄、绿三种颜色的球,其中红球3个,黄球3个,绿球6个。现将这12个球混放在一个盒子中,从中任意摸出8个球,编程计算摸出球的每种颜色搭配。
程序代码:
#include
#include
main(){
int red,yellow,green;
for(red=0;red<=3;red++)
for(yellow=0;yellow<=3;yellow++)
for(green=2;green<=8;green++)
if(red+yellow+green==8)
printf("%d %d %d\n",red,yellow,green);
}
5.百钱买百鸡问题
题目要求:我国古代数学家张邱建在《算经》一书中提出过著名的“百钱买百鸡”问题。该问题叙述如下:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡,则翁、母、雏各几何?请编写C程序,解决“百钱买百鸡”问题。
程序代码:
#include
#include
main(){
int a,b,c;
for(a=0;a<=20;a++)
for(b=0;b<=33;b++)
for(c=0;c<=300;c++)
if(a*5+b*3+c/3==100 && a+b+c==100 && c%3==0)
printf("有鸡翁、鸡母、雏鸡各%d、%d、%d只\n",a,b,c);

}
6.判断回文数字
题目要求:有这样一类数字,他们顺着看和倒着看是相同的数字,例如121、656、2332等,这样的数字叫做回文数字。编写一个程序,判断从键盘接收的数字是否为回文数字。
程序代码:
#include
#include
int reverse(num){//求i的倒置数
int m,j=0;
m=num;
while(m){
j=j*10+m%10;
m=m/10;
}
return j;
}
int isCircle(int num){//判断n是否为回文数
int mun;
mun=reverse(num);
if(num==mun)
return 1;
else
return 0;
}

main(){
int num;
printf("请输入一个数字:\n");
scanf("%d",&num);
if(isCircle(num))
printf("该数字是回文数字\n");
else
printf("该数字不是回文数字\n");
}
7.填数字游戏求解
题目要求:有这样一个算式:
ABCD
* E
----
DCBA
其中,ABCDE代表的数字各不相同。编写一个程序,计算出ABCD各代表什么数字。
题目分析:这道题目的实质就是求一个4位数ABCD和1位数E,要求他们的乘积等于DCBA。同时A、B、C、D、E互不相同。也就是在4位的整数集合[1000,9999]和1位的整数集合[1,9]中找到符合上述条件的4位数ABCD和1位数E。
程序代码:
#include
int reverse(i){//求r的倒置数
int r=0;
while(i){
r=r*10+i%10;
i=i/10;
}
return r;
}
int fun(int i,int j){//判断ABCDE均不相等

int buf[4],k=0,m,n;
int flag1=1,flag2=1;
while(i){
buf[k]=i%10;
i=i/10;
k++;
}
for(k=0;k<4;k++)//判断buf[]与j是否相等
if(buf[k]==j){
flag1=0;
break;
}
for(m=0;m<4;m++)
for(n=m+1;n<4;n++)
if(buf[m]==buf[n]){
flag2=0;
break;
}
return (flag1*flag2);
}
main(){
int i,j;
for(i=1000;i<=9999;i++)
for(j=1;j<=9;j++)

if((i*j==reverse(i)) && fun(i,j)){
printf("%d\n",i);
printf("* %d\n",j);
printf("-----\n");
printf("%d\n",i*j);
}
}
8.新郎与新娘
题目要求:3对新婚夫妇参加婚礼,3个新郎为A、B、C,3个新娘为X、Y、Z。有人不知道谁和谁结婚,于是询问了6位新人中的3位,但听到的答案是这样的:A说他将和X结婚;X说她的未婚夫是C;C说他将和Z结婚。这人听后知道他们在开玩笑,全是假话。请编程找出谁将和谁结婚。
程序代码:
#include
int match(int i,int j,int k,char wife[]){
if(wife[i]=='X')//A不和X结婚
return 0;
if(wife[k]=='X')//B不和X结婚
return 0;
if(wife[k]=='Z')//C不和Z结婚
return 0;
return 1;
}
main(){
char husband[3]={'A','B','C'},wife[3]={'X','Y','Z'};
int i,j,k;
for(i=0;i<3;i++)//A对应的wife为0,1,2中的一个
for(j=0;j<3;j++)//B对应的
for(k=0;k<3;k++)//C对应的
if(i!=j && i!=k && j!=k){
if(match(i,j,k,wife)){
printf("husband wife\n");
printf("A--%c\n",wife[i]);
printf("B--%c\n",wife[j]);
printf("C--%c\n",wife[k]);
}
}
}
9.爱因斯坦的阶梯问题
题目要求:爱因斯坦曾出过这样一道有趣的数学题:有一个长阶梯,若每步上2阶,最后剩1阶;若每步上3阶,最后剩2阶;若每步上5阶,最后剩4阶;若每步上6阶,最后剩5阶;只有每步上7阶,最后刚好一阶也不剩。请问该阶梯至少有多少阶。编写一个C程序解决该问题。
程序代码:
#include
main(){
int flag=0;
int i,res;
for(i=7;i<=120;i++)
if(i%7==0 && i%2==1 && i%3==2 && i%5==4 && i%6==5){
flag=1;
res=i;
break;
}
if(flag==1)
printf("the result of the Einstein's question is %d\n",res);
else
printf("in the range cannot get the result\n");
}
10.寻找水仙花数
题目要求:如果一个3位数等于其各位数字的立方和,则称这个数为水仙花数。例如:407=4*4*4+0*0*0+7*7*7,因此407就是一个水仙花数。编写一个程序,找出所有的水仙花数。
程序代码:
#include
#include
main(){
int i;
int ge,shi,bai;
for(i=100;i<=999;i++){
ge=i%10;
shi=(i/10)%10;
bai=i/100;
if(i==pow(ge,3)+pow(shi,3)+pow(bai,3))
printf("%d\t",i);
}

}
11.猴子吃桃问题
题目要求:一只猴子第一天摘下若干个桃子,当即吃掉了一半,又多吃了一个;第二天又将剩下的桃子吃掉一半,又多吃一个;按照这样的吃法每天都吃前一天剩下的桃

子的一半又一个,到了第十天,就只剩下一个桃子。问题:这只猴子第一天摘了多少个桃子。
程序代码:
#include
#include
main(){
int i,sum=1;
for(i=0;i<9;i++)
sum=(sum+1)*2;
printf("the number of the peach is %d\n",sum);
}
12.兔子产仔问题
题目要求:13世纪意大利数学家斐波那契的《算盘书》中提出这样一个问题:有人想知道一年内一对兔子可繁殖成多少对,便筑了一道围墙把一对新生的兔子关在里面。已知一对两个月大的兔子以后每一个月可以生一对小兔子,而一对新生的兔子出生两个月后才可以生小兔子(例如:1月份出生,3月份才可产仔)。假如一年内没发生死亡,则一年内共能繁殖成多少对?
问题分析:
从第3个月开始,每个月的兔子总数为=前两个月兔子的总和。这就是著名的斐波那契额数列。
程序代码:
#include
#include
int Fibonacci(int n){
if(n==1 || n==2)
return 1;
else
return Fibonacci(n-1)+Fibonacci(n-2);
}
main(){
printf("there are %d pairs rabbits a year late\n",Fibonacci(12));

}
13.分解质因数
题目要求:根据数论的知识可知任何一个合数都可以写成几个质数相乘的形式,这几个质数都叫做这个合数的质因数。例如24=2*2*2*3。把一个合数写成几个质数相乘的形式表示,这叫分解质因数。对于一个质数,它的质因数可定义为它本身。编写一个程序实现分解质因数。
程序代码:
#include
#include
int isPrime(int i)
{//判断一个数是否为素数
int flag=1,n;
if(i==1)
flag=0;
for(n=2;nif(i%n==0)
{
flag=0;
break;
}
if(flag==1)
return 1;
else
return 0;
}

void fenjie(int num)
{
int i;
if(isPrime(num))
printf("%d ",num);
else
{
for(i=2;i<=num-1;i++)
{
if(num%i==0)
{
printf("%d ",i);
if(isPrime(num/i))
{
printf("%d ",num/i);
break;
}
else
fenjie(num/i);
break;
}
}
}
}

main(){
int num;
printf("please input a number:\n");
scanf("%d",&num);
fenjie(num);
}
14.常胜将军
题目要求:现有12根火柴,两人轮流取走1-4根,不可多取,也不能不取,谁取最后一根火柴谁输。请编写一个程序进行人机对弈,要求人先取,计算机后取;计算机一方称为“常胜将军”。
问题分析:想要计算机是“常胜将军”,也就是要让人取到最后一根火柴。只有一种可能,那就是让计算机给人只剩下1根火柴。因为此时人至少取1根火柴。别的情况都不能保证计算机常胜。
于是问题转化为“有20根火柴,两人轮流取,每人每次可以取走1至4根,不可多取,也不能少取,要求人先取,计算机后取,谁取最后一根

火柴谁赢”。为了让计算机取到最后一根火柴,就要保证最后一轮的抽取(人先取一次,计算机再取一次)之前剩下5根火柴。因为只有这样,无论人怎么取火柴,计算机都要将其余的火柴全部取走。
于是问题又转化为“15根火柴,两人轮流取,每人每次可以取走1至4根,不可多取,也不能少取,要求人先取,计算机后取,保证计算机取到最后一根火柴”。同样道理,为了让计算机取到最后一根火柴,就要保证最后一轮的抽取(人先取一次,计算机再取一次)之前剩下5根火柴。
于是问题又转换为10根火柴的问题。。。依次递推。
最后可以得到这样的结论:21根火柴,在人先取,计算机后取,每次取1-4根的前提下,只要保证每一轮的抽取(人先取一次,计算机再取一次)人抽到的火柴数与计算机抽到的火柴数之和为5就可以实现计算机的长胜不败。
程序代码:
#include
#include
main(){
int computer,people,spare=21;
printf("----------------------------");
printf("---你不能战胜我,不信试试---");
printf("----------------------------");
printf("Game begin:\n\n");
while(1)
{
printf("------目前还有%d根--------\n",spare);
printf("People:");
scanf("%d",&people);
if(people<1 || people>4 || people>spare)
{
printf("你违规了,你取得火柴数有问题!\n\n");
continue;
}
spare=spare-people;
if(spare==0)
{
printf("\nComputer win!Game Over!\n");
break;
}
computer=5-people;
spare=spare-computer;
printf("Computer:%d \n",computer);
if(spare==0)
{
printf("\nPeople win!Game Over!\n");
break;
}
}
}
15.求PI的近似值
题目要求:编写一个C程序,用来求出PI的近似值。
题目分析:
求PI的方法很多,这里两种最为常用的求PI的方法。
方法一:利用“正多边形逼近”法求PI
“正多边形逼近”法求PI的核心思想就是极限的思想。假设一个直径d为1的圆,只要求出该圆的周长C,就可以通过PI=C/d的方法求出PI的值。所以关键是求出该圆的周长C。这里用“多边形逼近”的方法求圆的周长。
设单位圆的内接多边形的边长为b,边数为i,则多边形边数加倍后,新多边形边长为:x=sqrt(2-2*sqrt(1-b*b))/2。其中sqrt为开方运算。这样,新多边形的边长就为:C=2*i*x,而原多边形的周长为:C=b*i;
如果最初单位圆的内接多边形为正四边形,其边长为sqrt(2)/2,于是b=sqrt(2)/2,i=4。那么边长加倍后,新八边形的边长为sqrt(2-2*sqrt(1-(sqrt(2)/2)*(sqrt(2)/2)))/2,i=8。如此迭代,可求出十六边形、三十二边形...的边长,再
再乘以相应的边数得到周长C,用这个周长C来近似代替其外接圆的周长,进而求出PI的近似值。
方法二:应用数值概率算

法求PI
数值概率算法又叫做随机数方法。它是利用概率论的思想解决实际问题的。
利用数值概率算法求PI的核心思想是:在一个边长为r的正方形中,以一个顶点为圆心,r为半径作一个1/4圆,随机向该正方形中投入点,其中落入该1/4圆内的点的概率的4倍就是PI的近似值。
随机点落入1/4圆中概率为1/4圆面积与边长为r的正方形面积的比值,即(1/(4*PI*r*r)):(r*r),结果为1/4*PI。
程序代码:
(1)利用“正多边形逼近”法求PI
#include
#include
double getPI(int n);
main(){
int n;
double PI;
printf("Please enter accuracy\n");
scanf("%d",&n);
PI=getPI(n);
printf("The similar value of PI is\n%f\n",PI);
}
double getPI(int n)
{
int div,i=4;
double b=sqrt(2)/2.0;
double c=0.0;
for(div=0;div{
b=sqrt(2.0-2.0*sqrt(1.0-b*b))*0.5;
i=i*2;
}
c=b*i;
return c;
}
(2)应用数值概率算法求PI
#include
#include
#include
double getPI(int n);
main(){
int n;
double PI;
printf("Please enter the number of random points for test\n");
scanf("%d",&n);
PI=getPI(n);
printf("The similar value of PI is:\n%f\n",PI);
}
double getPI(int n)
{
int inCircle=0;
int x,y;
int count=n;
while(count)
{
x=rand()%101;
y=rand()%101;
if(x*x+y*y<=10000)
inCircle++;
count--;
}
return 4.0*inCircle/n;
}
16.魔幻方阵
题目要求:有一种方阵被称为“魔鬼方阵”。所为魔鬼方阵是指在n*n的矩阵中填写1-n*n这n*n个数字,使得它的每一行、每一列以及两个对角线之和均相等。例如三阶方阵如下:
8 1 6
3 5 7
4 9 2
它的每一行、每一列以及两个对角线之和均为15,编写一个程序,打印出一种三阶的魔幻矩阵。
程序代码:
#include
#include
#include
int match(int i,int j,int k,int l,int m,int n,int o,int p,int q)
{
//判断变量i-q是否互不相等,是则返回去1,不是则返回0
if(i!=j && i!=k && i!=l && i!=m && i!=n && i!=o && i!=p && i!=q
&& j!=k && j!=l && j!=m && j!=n && j!=o && j!=p && j!=q
&& k!=l && k!=m && k!=n && k!=o && k!=p && k!=q
&& l!=m && l!=n && l!=o && l!=p &&l!=q
&& m!=n && m!=o && m!=p &&m!=q
&& n!=o && n!=p && n!=q
&& o!=p && o!=q
&& p!=q)
return 1;
else
return 0;
}
int justic(int i,int j,int k,int l,int m,int n,int o,int p,int q)
{
/*判断变量i-q的这种排列是否满足魔幻方阵的要求,满足则返回1,不满足返回0*/
if(i+j+k == l+m+n && i+j+k == o+p+q &&
i+l+o == j+m+p && i+l+o == k+n+q
&& i+m+q == k+m+o)
return 1;
else
return 0;
}
void getMatrix()
{
int i,j,k,l,m,n,o,p,q;
for(i=1;i<=9;i++)
for(j=1;j<=9;j++)
for(k=1;k<=9;k++)
for(l=0;l<=9;l++)
for(m=0;m<=9;m++)
for(n=0;n<=9;n++)
for(o=1;o<=9;o++)
for(p=1;p<=9;p++)
for(q=1;q<=9;q++)

{
if(match(i,j,k,l,m,n,o,p,q))
if(justic(i,j,k,l,m,n,o,p,q))
{
printf("%d %d %d\n",i,j,k);//输出结果
printf("%d %d %d\n",l,m,n);
printf("%d %d %d\n",o,p,q);
}
printf("\n");
}
}
main(){
getMatrix();

}
17.移数字游戏
题目要求:有这样一个包含9个圆圈的矩阵,如(上)图:
[]-[]-[]
| \ | /|
[]-[]-[]
| / | \|
[]-[]-[](上)

[1]-[2]-[3]
| \ |- /|
[8]-[ ]-[4]
| / | \|
[7]-[6]-[5](下)
将1-8这8个数随机地填写到该数阵的外层的圆圈中,只剩下中间的一个空圆圈。规定每个数字只能按照数阵中的直线从一个圆圈移动到另一个空的圆圈中。通过若干步的移动,要求将该数阵中的数字移动成(下)图所示
程序代码:
#include
#include
#include
void Print(int a[])
{
printf("[%d] [%d] [%d]\n",a[0],a[1],a[2]);
printf("| %c | %c |\n",92,47);
printf("[%d] [] [%d]\n",a[7],a[3]);
printf("| %c | %c |\n",47,92);
printf("[%d] [%d] [%d]\n",a[6],a[5],a[4]);
}
void getStep(int a[])//显示数阵中数据移动的步骤
{
int i,j,temp;
for(i=0;i<7;i++)//冒泡排序
for(j=0;j<7-i;j++)
{
if(a[j]>=a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
printf("%d#->0#\n",a[j]);
printf("%d#->%d#\n",a[j+1],a[j]);
printf("0#->%d#\n",a[j+1]);
}
}
}
main()
{
int a[8],i;
printf("please input 8 integer (1-8) to array this matrix:\n");
for(i=0;i<8;i++)
scanf("%d",&a[i]);
printf("the inital data matrix is like:\n");
Print(a);
printf("\nMove step:\n");
getStep(a);
printf("the result of moving is:\n");
Print(a);
}
18.数字的全排列
题目要求:输入一个数字序列{a1,a2,...,an},并输入每一种排列方式。例如:输入数字序列:1,3,5.该数列共有6种排列方式,分别为:
1,3,5 1,5,3 3,1,5 3,5,1 5,1,3 5,3,1
编写一个C程序,实现数字序列的全排列。
题目分析:在这个算法中,参数a[]为待排序的数组;参数n为当前数组中的元素的个数,这个数会随着递归的调用发生变化。确切的说,n为当前子序列中元素的个数。参数r[]为排序后的数组,即它存放数组a的每一种排序结果。参数s为数组r的下标。参数m为原始数组a中元素的个数,这个数不会发生变化。
在算法中,数组b[]的作用是存放数列a中除去a[i]的其他元素,也就是每一层递归操作生成的子序列。将数组b作为递归调用Perm的实参进行传递,此时序列中的个数n减1,存放排序结果的数组r的下标加1.变量flag为一个标志变量。当flag为0时,表明已经得到数组a的一个排序结果,存放在数组r中,因此输出r中的结果(m个元素)。当flag为1时,表示尚未得到排序结果,需要继续递归求解。
程序代码:
#include
#inc

lude
#include
#define max 100
Perm(int a[],int n,int s,int r[],int m)
{
int i,j,k,flag=0;
int b[max];
for(i=0;i{
flag=1;
r[s]=a[i];
j=0;
for(k=0;kif(i!=k)
{
b[j]=a[k];
j++;
}
Perm(b,n-1,s+1,r,m);
}
if(flag==0)
{
printf("\n");
for(k=0;kprintf("%d ",r[k]);
printf("\n");
}
}
main()
{
int a[max],r[max];
int i,n;
printf("Please input the number of digit in the array\n");
scanf("%d",&n);
printf("Please input a string for array\n");
for(i=0;iscanf("%d",&a[i]);
Perm(a,n,0,r,n);
}
19.完全数
题目要求:如果一个数恰好等于它的因子之和,那么这个数被称为完全数。例如6的因子为1、2、3,而6=1+2+3,因此6是一个完全数。求出1000以内的完全数。
程序代码:
#include
#include
#include
int factorSum(a)
{
int i,sum=0;
for(i=1;i{
if(a%i==0)
sum+=i;
}
return sum;
}
int perfextnumber(int a)
{
if(a==factorSum(a))
return 1;
else
return 0;
}
main()
{
int i;
printf("1000以内的完全数为:\n");
for(i=1;i<=1000;i++)
{
if(perfextnumber(i))
printf("%d ",i);
}
printf("\n");
}
20.亲密数
题目要求:如果整数A的全部因子(包括1,不包括A本身)之和等于B,并且整数B的全部因子(包括1,不包括B本身)之和等于A,则称整数A和B为亲密数。求解3000以内的全部亲密数。
题目分析:在一个数集{x1、x2、...、xn}中寻找亲密数,可以针对每一个元素,在其他的元素中寻找该元素的亲密数。为了使寻找亲密数的效率更高,可以逻辑上划分两个子集A和B,最初数集中所有的元素都放在子集合B中。
然后在集合B中任选一个元素放入集合A中,同时在集合B中删除该元素。然后在集合B中的其他元素中寻找刚刚放入集合A中的那个元素的亲密数。如果在集合B中找到了刚刚放入集合A中的那个元素的亲密数,则将该亲密数(不妨设为xi)也放入集合A中,同时在集合B中删去xi。
然后重复上述操作,在集合B中任选一个元素,放入集合A中,在集合B中寻找它的亲密数...。
如果在集合B中没有找到刚刚放入集合A中的那个元素的亲密数,则重复上述操作,在集合B中任选一个元素,放入集合A中,在集合B中寻找它的亲密数...。
上述操作直到子集B中的元素全部放到子集A中为止。
比较亲密数的合理做法是:实现全部计算出1-3000以内所有整数的因子的和,存放到数组x[]中,这样x[i]中存放的是i的因子之和。其中判断j和i是否为亲密数的方法是:判断x[j]是否等于i,以及判断x[i]是否等于j。
程序代码:
#include
#include
#include
int factorSum(a)/*求a的因子和*/
{
int i,sum=0;
for(i=1;i{


if(a%i==0)
sum+=i;
}
return sum;
}
int isfriend(int a,int b,int i,int j)/*判断a和b是否是亲密数,是亲密数返回1,否则返回0*/
{
if(a==j && b==i)
return 1;
else
return 0;
}
friendly()/*寻找1-3000范围内的亲密数*/
{
int i,j,x[3001];
for(i=1;i<=3000;i++)
x[i]=factorSum(i);
for(i=1;i<=3000;i++)
{
if(x[i]!=-111)
{
for(j=i+1;j<=3000;j++)
if(isfriend(x[i],x[j],i,j))
{
printf("(%d %d) ",i,j);
x[j]=-111;//表示j已经找到亲密数
}
}
}
}
main()
{
printf("There are following friendly numbers from 1 to 3000\n");
friendly();
printf("\n");
}
21.数字翻译器
题目要求:输入一个正整数N,输出它的英文表达。例如:输入1,输出one;输入12,输出twelve;输入135,输出one hundred thirty five...。编写程序实现之。
程序代码:
#include
#include
#include
char data1[20][10]={"zero","one","two","three","four","five","six","seven","eight","nine","ten",
"eleven","twelve","thirteen","forteen","fifteen","sixteen","seventeen","eighteen","ninteen"};
char data2[8][7]={"twenty","thirty","forty","fifty","sixty","seventy","eighty","ninty"};
translation_geshi(long a)/*翻译十位数和个位数*/
{
long b,c;
if(a>=0 && a<=19)
printf("%s ",data1[a]);
else
{
b=a/10;
printf("%s ",data2[b-2]);
c=a%10;
if(c!=0)
printf("%s ",data1[c]);
}
}
translation_bai(long a)/*翻译百位数*/
{
long b,c;
b=a/100;
if(b!=0)
{
translation_geshi(b);
printf("hundred ");
}
c=a%100;
if(c!=0)
translation_geshi(c);
}
translation_qian(long a)
{
long b,c;
b=a/1000;
if(b!=0)
{
translation_bai(b);
printf("hundred and ");
}
c=a%1000;
if(c!=0)
translation_bai(c);
}
main()
{
long n;
printf("please input a long number from 0-999999:\n");
scanf("%ld",&n);
translation_qian(n);
}
22.递归实现数字转换
题目要求:应用递归的方法实现一个数制转换器,它可以将输入的二进制数转换为十进制表达式。
程序说明:算法中参数sum用来记录累加和,参数m随着递归的深入不断增加1,并且递归结束m的值也不会发生改变。因为参数sum和m都要在递归中保持值不变,因此采用指针传递方式。参数n的值随着递归的深入不断加1,但是每一层的递归n的值都不相同。

第一层递归 第二层递归 第三层递归 第四层递归
BiTOde BiTOde BiTOde BiTOde
输入1 输入1 输入0 输入#

m=1 m=2 m=3 c='#'
n=0 ---------> n=1 --------> n=2 --------> m=3
BiTOde BiTOde BiTOde n=3

(m=3,n=0) <------- (m=3,n=1) <------ (m=3,n=2) <------ (m=3,n=3)
sum=pow(2,1)+ sum=pow(2,3-1-1) 由于输入为0, 返回
pow(2,3-0-1) 故sum=0
<最终答案>

程序代码:
#include
#include
#include
BiTOde(int n,double

*sum,int *m)
{
char c;
scanf("%c",&c);
if(c!='#')
{
*m=*m+1;
BiTOde(n+1,&(*sum),&(*m));
}
if(c=='1')
*sum=*sum+pow(2,(*m)-n-1);
}
main()
{
double sum=0.0;
int m=0;
printf("Please input a binary number ending for '#'\n");
BiTOde(0,&sum,&m);
printf("The decimal digit is:\n");
printf("%g \n",sum);
}
23.谁在说谎
题目要求:3个嫌疑犯在法官面前各执一词,甲说:乙在说谎;乙说:丙在说谎;丙说:甲乙两人都在说谎。法官为了难,甲乙丙三人到底谁在说谎,谁说的是真话?
题目分析:用1表示真,用0表示假,则甲乙丙三人所说的话的真假情况限定在8个范围。甲乙丙:000,001,010,011,100,101,110,111.
设甲乙丙三人所说的话的真假用变量a、b、c表示,则a、b、c的取值为1或0.按照甲乙丙所说的话,存在如下逻辑关系:
如果a=1,则b=0;如果a=0,则b=1;如果b=1,则c=0;如果b=0,则c=1;如果c=1,则a+b=0;如果c=0,则a+b!=0;
因此,要判断3个人所说画的真伪,必须使他们的话符合逻辑。即满足一下关系:
[(a==1 && b==0)||(a==0 && b==1)]&&[(b==1 && c==0)||(b==0 && c==1)]&&[(c==1 && a+b==0)||(c==0 && a+b!=0)]
=>(a&&!b||!a&&b)&&(b&&!c||!b&&c)&&(c&&a+b==0||!c&&a+b!=0)
凡是不满足以上的逻辑表达式判断的组合都不是正确答案,只有所有结果为真的组合才是本题的正确答案。
程序代码:
#include
#include
#include
main()
{
int a,b,c;
for(a=0;a<=1;a++)
for(b=0;b<=1;b++)
for(c=0;c<=1;c++)
{
if((a && !b||!a && b) && (b && !c||!b && c) && ((c&&(a+b==0))||(!c&&(a+b!=0))))
{
printf("甲 told a %s\n",a?"true":"lie");
printf("乙 told a %s\n",b?"true":"lie");
printf("丙 told a %s\n",c?"true":"lie");
}
}
}































相关主题
相关文档
最新文档