回顾一下吧:
一、
有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
解析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。
常规写法:
#include<stdio.h> int main() { int i,j,k; printf(" "); for(i=1;i<5;i++) { // 以下为三重循环 for(j=1;j<5;j++) { for (k=1;k<5;k++) { // 确保i、j、k三位互不相同 if (i!=k&&i!=j&&j!=k) { printf("%d,%d,%d ",i,j,k); } } } } }
避免一些不必要的循环,下面是优化写法:
#include<stdio.h> int main() { int i,j,k; for(i=1;i<5;i++) { for(j=1;j<5;j++) { if(i==j)//百位与十位重复,跳过当前十位 continue; for(k=1;k<5;k++) { if(i==k||j==k)//百位与个位重复,或十位与个位重复 continue; printf("%d %d %d ",i,j,k); } } } return 0; }
二、
企业发放的奖金根据利润提成。
- 利润(I)低于或等于10万元时,奖金可提10%;
- 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;
- 20万到40万之间时,高于20万元的部分,可提成5%;
- 40万到60万之间时高于40万元的部分,可提成3%;
- 60万到100万之间时,高于60万元的部分,可提成1.5%;
- 高于100万元时,超过100万元的部分按1%提成。
从键盘输入当月利润I,求应发放奖金总数?
#include<stdio.h> int main() { double i; double bonus1,bonus2,bonus4,bonus6,bonus10,bonus; printf("您好,请输入您的净利润: "); scanf("%lf",&i); bonus1=100000*0.1; bonus2=bonus1+100000*0.75; bonus4=bonus2+200000*0.05; bonus6=bonus4+200000*0.03; bonus10=bonus6+400000*0.015; if(i<100000) { bonus=i*0.1; } else if(i<=200000) { bonus=bonus1+(i-100000)*0.075; } else if(i<=400000) { bonus=bonus2+(i-200000)*0.05; } else if(i<=600000) { bonus=bonus4+(i-200000)*0.03; } else if(i<=1000000) { bonus=bonus6+(i-400000)*0.015; } else if(i>1000000) { bonus=bonus10+(i-1000000)*0.001; } printf("您获得的提成为:bonus=%lf. ",bonus); return 0; }
用循环优化:
#include<stdio.h> int main() { int i; double lirun; double jiangjin = 0; float fanwei[] = {100000, 200000, 400000, 600000, 1000000}; float ticheng[] = {0.1, 0.075, 0.05, 0.03, 0.015, 0.01}; printf("您好,请问您的净利润是多少? "); scanf("%lf", &lirun); for (i=0;i<5;i++) { if (lirun < fanwei[i]) { jiangjin += lirun * ticheng[i]; break; } else { jiangjin += fanwei[i] * ticheng[i]; lirun -= fanwei[i]; } } printf("提成是%.2lf ", jiangjin); return 0; }
三、
题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
程序分析:
假设该数为 x。
1、则:x + 100 = n2, x + 100 + 168 = m2
2、计算等式:m2 - n2 = (m + n)(m - n) = 168
3、设置: m + n = i,m - n = j,i * j =168,i 和 j 至少一个是偶数
4、可得: m = (i + j) / 2, n = (i - j) / 2,i 和 j 要么都是偶数,要么都是奇数。
5、从 3 和 4 推导可知道,i 与 j 均是大于等于 2 的偶数。
6、由于 i * j = 168, j>=2,则 1 < i < 168 / 2 + 1。
7、接下来将 i 的所有数字循环计算即可。
/*一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?*/ #include<stdio.h> int main() { int i,j,m,n,x; for(i=1;i<168/2+1;i++) { if(168%i==0) { j=168/i; if(i>j&&(i+j)%2==0&&(i-j)%2==0) { m=(i+j)/2; n=(i-j)/2; x=n*n-100; printf("%d+100=%d*%d ",x,n,n); printf("%d+100+168=%d*%d ",x,m,m); } } } return 0; }
四、
古典问题(兔子生崽):有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?(输出前40个月即可)
分析(及其易懂了):
说明:δ1表示出生第一个月的兔子数量,δ2表示出生第二个的兔子数量,δ3表示出生第三个月即成熟的兔子数量(单位:对)。也就是只有标注为δ3的兔子对才能生出新的一对δ1。下面分析中我们直接以δ出现的个数表示现存的兔子对数。
第一个月:δ1 (1只)
第二个月:δ2 (1只)
第三个月:δ3+ δ1 (2只)
第四个月:δ3+ δ1+ δ2 (3只)
第五个月:δ3+ δ1+ δ2+ δ3+ δ1 (5只)
第六个月:δ3+ δ1+δ2+ δ3+ δ1+δ3+ δ1+δ2 (8只)
第七个月:δ3+δ1+δ2+δ3+δ1+δ3+δ1+δ2+δ3+δ1+δ2+δ3+δ1 (13只)
以此类推。。。(为便于观察理解,上述分析中,上下能对应的是同一只兔子的生长状态,纵向观察一下这些可爱的δ,有没有发现更容易理解了呢)
用数组:
#include <stdio.h> int main() { int n[41],i; //i表示月份 n[0]=0; //赋值 n[1]=1; n[2]=1; for(i=3;i<41;i++)//计算从第三个月开始的兔子数量,i=3 { n[i]=n[i-1]+n[i-2]; } printf("month number "); //输出 for(i=1;i<41;i++)//输出自第一个月开始的兔子数量,i=1 { printf("%d %d ",i,n[i]); } return 0; }
下面是递归方式,运行一下你会发现,时间复杂度较大,运算效率很低:
//斐波那契数列 #include<stdio.h> int fibonaci(int i) { if(i == 0) { return 0; } if(i == 1) { return 1; } return fibonaci(i-1) + fibonaci(i-2); } int main() { int i; printf("month number "); for (i = 1; i < 41; i++) { printf("%d %d ", i,fibonaci(i)); } return 0; }
五、
判断101到200之间的素数。
分析:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。
#include<stdio.h> #include<math.h> int main() { int i,j,k; for(i=101;i<201;i++) { k=sqrt(i); //如果i不能被2~√i间任一整数整除,i必定是素数 for(j=2;j<=k;j++) if(i%j==0) break; if(j>k) printf("%d ",i); } }
六、打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数 本身。例如:153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方。
分析:利用for循环控制100-999个数,每个数分解出个位,十位,百位。
#include<stdio.h> int main() { int i,x,y,z; for(i=100;i<1000;i++) { x=i%10;//个位数 y=i/10%10;//十位数 z=i/100%10;//百位数 if(i==(x*x*x+y*y*y+z*z*z)) printf("%d ",i); } return 0; }
七、将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
分析:
对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:
- (1)如果这个质数恰等于(小于的时候,继续执行循环)n,则说明分解质因数的过程已经结束,另外 打印出即可。
- (2)但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数n.重复执行第二步。
- (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。
#include<stdio.h> int main() { int n,i; printf("请输入整数:"); scanf("%d",&n); printf("%d=",n); for(i=2;i<=n;i++) { while(n%i==0) { printf("%d",i); n/=i; if(n!=1) printf("*"); } } printf(" "); return 0; }
八、输入两个正整数m和n,求其最大公约数和最小公倍数。
程序分析:
(1)最小公倍数=输入的两个数之积除于它们的最大公约数,关键是求出最大公约数;
(2)求最大公约数用辗转相除法(又名欧几里德算法)
1)证明:设c是a和b的最大公约数,记为c=gcd(a,b),a>=b,
令r=a mod b
设a=kc,b=jc,则k,j互素,否则c不是最大公约数
据上,r=a-mb=kc-mjc=(k-mj)c
可知r也是c的倍数,且k-mj与j互素,否则与前述k,j互素矛盾,
由此可知,b与r的最大公约数也是c,即gcd(a,b)=gcd(b,a mod b),得证。
2)算法描述:
第一步:a ÷ b,令r为所得余数(0≤r<b);
第二步:互换:置 a←b,b←r,并返回第一步。
附:辗转相除法
有两整数a和b:
① a%b得余数c
② 若c=0,则b即为两数的最大公约数
③ 若c≠0,则a=b,b=c,再回去执行①
例如求27和15的最大公约数过程为:
27÷15 余1215÷12余312÷3余0因此,3即为最大公约数
#include<stdio.h> int main() { int a,b,t,r; printf("请输入两个数字: "); scanf("%d %d",&a,&b); if(a<b) { t=b; b=a; a=t; } r=a%b; int n=a*b; while(r!=0)//辗转相除法 { a=b; b=r; r=a%b; } printf("这两个数的最大公约数是%d,最小公倍数是%d ",b,n/b); return 0; }
九、打印出杨辉三角形(要求打印出10行)。
#include <stdio.h> int main() { int i,j; int a[10][10]; printf(" "); for(i=0;i<10;i++) { a[i][0]=1; a[i][i]=1; } for(i=2;i<10;i++) for(j=1;j<i;j++) a[i][j]=a[i-1][j-1]+a[i-1][j]; for(i=0;i<10;i++) { for(j=0;j<=i;j++) printf("%5d",a[i][j]); printf(" "); } }
结构如下所示:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
十、创建一个链表。
分析:
#include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef struct node { int data; struct node *next; }node,*Linklist; Linklist CreateList(int n) { int i = 1; Linklist L,rear,s; L = (node*)malloc(sizeof(node)); if(!L) return 0; L->next = NULL; rear = L; while(n) { s = (Linklist)malloc(sizeof(node)); printf("请输入第%d个数:",i++); scanf("%d",&(s->data)); rear->next = s; rear = s; n--; } rear->next = NULL; return L; } void Print(Linklist L) { Linklist p = L->next; while(p) { printf("%d ",p->data); p = p->next; } } int main(void) { Linklist L = NULL; int n; printf("请输入数据个数: "); scanf("%d",&n); L = CreateList(n); Print(L);
printf(" "); return 0; }
十一、反向输出一个链表。
#include <stdio.h> #include <stdlib.h> struct list { int data; struct list *next; }; typedef struct list node; typedef node *link; void main() { link ptr, head, tail; int num, i; tail=(link)malloc(sizeof(node)); tail->next=NULL; ptr=tail; printf("Please enter 5 data ==> "); for(i=0; i <= 4; i++) { scanf("%d", &num); ptr->data=num; head=(link)malloc(sizeof(node)); head->next=ptr; ptr=head; } ptr=ptr->next; while(ptr != NULL) { printf("The value is ==>%d ", ptr->data); ptr=ptr->next; } }
十二、连接两个链表。
#include <stdlib.h> #include <stdio.h> struct list { int data; struct list *next; }; typedef struct list node; typedef node *link; link delete_node(link pointer,link tmp) { if (tmp==NULL) /*delete first node*/ return pointer->next; else { if(tmp->next->next==NULL)/*delete last node*/ tmp->next=NULL; else /*delete the other node*/ tmp->next=tmp->next->next; return pointer; } } void selection_sort(link pointer,int num) { link tmp,btmp; int i,min; for(i=0;i<num;i++) { tmp=pointer; min=tmp->data; btmp=NULL; while(tmp->next) { if(min>tmp->next->data) { min=tmp->next->data; btmp=tmp; } tmp=tmp->next; } printf("40: %d ",min); pointer=delete_node(pointer,btmp); } } link create_list(int array[],int num) { link tmp1,tmp2,pointer; int i; pointer=(link)malloc(sizeof(node)); pointer->data=array[0]; tmp1=pointer; for(i=1;i<num;i++) { tmp2=(link)malloc(sizeof(node)); tmp2->next=NULL; tmp2->data=array[i]; tmp1->next=tmp2; tmp1=tmp1->next; } return pointer; } link concatenate(link pointer1,link pointer2) { link tmp; tmp=pointer1; while(tmp->next) tmp=tmp->next; tmp->next=pointer2; return pointer1; } int main(void) { int arr1[]={3,12,8,9,11}; link ptr; ptr=create_list(arr1,5); selection_sort(ptr,5); }
十三、输入一个整数,并将其反转后输出。
#include <stdio.h> int main() { int n,reverseNumber=0,remainder; printf("请输入一个整数:"); scanf("%d",&n); while(n!=0) { remainder=n%10; reverseNumber=reverseNumber*10+remainder; n/=10; } printf("反转后的整数是:%d ",reverseNumber); return 0; }
十四、编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n(利用指针函数)。
#include<stdio.h> #include<stdlib.h> double evenumber(int n); double oddnumber(int n); int main() { int n; double r; double (*pfunc)(int); printf("请输入一个数字:"); scanf("%d",&n); if(n%2==0) pfunc=evenumber;//偶数 else pfunc=oddnumber;//奇数 r=(*pfunc)(n); printf("%lf ",r); system("pause"); return 0; } double evenumber(int n)//偶数时,执行1/2+1/4+...+1/n { double s=0,a=0; int i; for(i=2;i<=n;i+=2) { a=(double)1/i; s+=a; } return s; } double oddnumber(int n)//奇数时,执行1/1+1/3+...+1/n { double s=0,a=0; int i; for(i=1;i<=n;i+=2) { a=(double)1/i; s+=a; } return s; }
十五、填空练习(指向指针的指针)。
#include<stdio.h> #include<stdlib.h> int main() { char *s[]={"man","woman","girl","boy","sister"}; char **q; int k; for(k=0;k<5;k++) { q=&s[k]; /*在这里填入内容*/ printf("%s ",*q); } return 0; }
十六、八进制转换为十进制
#include<stdio.h> #include<stdlib.h> int main() { int n=0,i=0; char s[20]; printf("请输入一个8进制数: "); gets(s); while(s[i]!='