C语言复习2

十六、齿轮重遇问题:三个齿轮啮合。在齿轮箱里三个齿轮相互衔接,某瞬间两对齿相遇。问各转多少圈后,这两对齿再次重逢。(说明:用a,b,c 分别表示三个齿轮的齿数。)
int main(){
 int i,a,b,c,m;
 scanf("%d%d%d",&a,&b,&c);
  //m=a>b?(a>c?a:c):(b>c?b:c);//a>b>c
  if(a<b){ 
   int k=a;
   a=b;
   b=k; 
  }
  if(b<c)
  {
   int temp = b;
   b=c;
   c=temp;
  }
  printf("a=%d,b=%d,c=%d\n",a,b,c);
 for(i=m;;i+=m) //每次要转m,所以要i+=m
  if(i%a==0 && i%b==0 && i%c==0)
   break;
 printf("%d\n",i);
  return 0;
}
十七、求13的13次方的最后三位数
void main()
{
 int i,j=13;
 int t=13;
 for(i=0;i<12;i++)
 {
  t = (j*t)%1000 ;
 }
 printf("%d\n",t);
}
十八、一个四位数的九倍等于它的反序数
void main()
{
 int i,j,x;
 int a[4];
 for(i=1000;i<=9999;i++){
  for(j=0,x=i;x>0;j++){ //拆分
   a[j] = x%10;
   x /= 10;
  }
  for(j=0,x=0;j<4;j++){ //组合
   x *= 10;
   x += a[j];
  }
  if(x==i*9)
   printf("原来的数=%d\n",i);

 }
}
十九、输出所有不超过n(n<256),其平方具有对称性质的数(也称回文数。)
#include "stdio.h"
//判断是否是回文(指针、数组),思路一定要清晰
int fun(int *a,int i,int j){
 if(i==j||j<i)  //仅剩一个数了
  return 1;
 if(a[i]==a[j])
  return  fun(a,i+1,j-1);
 else
  return 0;
 }
int main(){
 int i,j,m,n,a[20];
  scanf("%d",&n);
 for(i=11;i<n;i++){  //11*11=121第一个具有对称性质的数
  m=i*i;
 for(j=0;m>0;j++){
  a[j] = m%10;
  m /= 10;
 }
 if(fun(a,0,j-1))
  printf("i=%d,i*i=%d\n",i,i*i);
 }
 return 0;
}
二十、若一个口袋中放有12个球,其中有3个红的,3个白的和6个黑的,问从中任意取8个共有多少种不同的颜色搭配。(组合问题,与顺序无关)
void main(){
int i,j,n=0;
for(i=0;i<=3;i++){
 for(j=0;j<=3;j++){
  if(8-i-j<=6){
   printf("%d%d%d\n",i,j,8-i-j);
    n++;
  }
 }
}
 printf("%d\n",n);
}
二十一、分数之和:求这样的四个自然数p, q, r, s(p <= q <= r <= s),使得以下等式成立: 1/p+1/q+1/r+1/s=1。
#include "stdio.h"
int main(){
 int p,q,r,s;
 for(p=2;p<5;p++)
  for(q=p;q<7;q++)
   for(r=q;r<13;r++)
    for(s=r;s<43;s++)
     if(p*q*r+p*q*s+p*r*s+q*r*s==p*q*r*s)
      printf("%d,%d,%d,%d\n",p,q,r,s);
  return 0;
}
二十二、从n个数中取r个数的组合,列出所有可能(递归+回溯)
#include "stdio.h"
void fun(int *a,int n,int r){
 int i,j;
 for(i=n;i>=r;i--){
  a[r]=i;
  if(r>1)
    fun(a,i-1,r-1);
  else {
   for(j=a[0];j>0;j--)
    printf("%2d",a[j]);
    printf("\n");
   }
  }
 }
int main(){
 int n,r;
 int a[100];
 scanf("%d%d",&n,&r);
  a[0]=r;
  fun(a,n,r);
 return 0;
}
二十三、有n个硬币(n为偶数)正面朝上排成一排,
每次将n-1个硬币翻成朝上为止。编程让计算
机把翻硬币的最简过程及翻币次数打印出来
(用*代表正面,用0代表反面)。
基本形式:D[1]=0;d[2]=1
递归式:d[n]= (n-1)*( d[n-1] + d[n-2])
#include "stdio.h"
long int d(int n){
 if(n==1) return 0;
 if(n==2) return 1;
 else
  return (n-1)*( d(n-1)+d(n-2) );
 }
int main(){
 int n;
 printf("n=");
  scanf("%d",&n);
 while(n<=0){
  printf("Once more!");
  scanf("%d",&n);
 }
 printf("d=%ld\n",d(n));
  return 0;
}
二十四、成等差的素数:寻找6个成等差级数且小于160的素数。
[解]设级数为:n,n-d,n-2d,n-3d,n-4d,n-5d。若这6个数全为素数,则为要求的解。
这里d、n均是要寻找的。仍用穷尽法,d最大可为33。判断素数函数为isprime。
#include "stdio.h"
#include "math.h"
int isprime(int m){//判断是不是素数
 int i,k=(int)sqrt(m);
 if(m<=0)
  return 0;
 else
  for(i=2;i<=k;i++){
   if(m%i==0)
     break;
   }
 if(i>k) return 1;
 else return 0;
}
int main(){
 int n,d;  // d:等差数(1-33)      n:要求的数(7-160)
 for(d=1;d<=31;d++){
  for(n=160;n>=7;n--){
   if((isprime(n)==1) && isprime(n-d)==1)
    if(isprime(n-2*d)==1 && isprime(n-3*d)==1)
     if(isprime(n-4*d)==1 && isprime(n-5*d)==1)
      printf("%-6d%-6d%-6d%-6d%-6d%-6d\n",n,n-d,n-2*d,n-3*d,n-4*d,n-5*d);
     }
 }
 return 0;
}
二十五、发奖章:运动会连续开了n天,一共发了m枚奖章,第一天发1枚并剩下(m-1)枚的1/7,第二天发2枚并剩下的1/7,以后每天按此规律发奖章,在最后一天即第n天发了剩下的n枚奖章。问运动会开了多少天(n)?一
共发了几枚奖章? (m)
[解]由于题目涉及m-1的1/7,于是m-1应是7的倍数,即m=7x+1。递推x,寻找m、n。
#include "stdio.h"
/*
  m = 7x+1 

*/
int main(){
int b,m,n,x=0;
do{
 x++;
 m=7*x+1;
 n=1;
 b=1;
 while(m>n && b==1){
  m -= n;
 if(m%7==0)
  m = (m/7)*6;
 else
  b=0;
  n++;
 }
  printf("n=%d\tm=%d\n",n,7*x+1);
 }while(b==1);
return 0;
}
二十六、完全平方数:寻找具有完全平方数,且不超过7位数码的回文数。
所谓回文数是指这样的数,它的各位数码是左右对称的。例如121、676、94249等。
[解]判断一个数是否回文数,可以将其转化成字符判断。也可以分解数,所谓分解就是将数的后半段倒置后再与前半段比较。这里采用分解的方法,其函数为symm。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int symm(char *str,int index,int end){
  
 if(index>=end) return 1;
 if(str[index]==str[end])
  return symm(str,index+1,end-1);
  else return 0;
}
int main(){
 char str[10];
 long int i;
 int len;
 for(i=11;i*i<9999999;i++){ //最小的回文数是121,即 11*11
  ltoa(i*i,str,10); //将长整型转换为字符串,i*i是要转换的数值,str是存放字符串的指针,10是表示转换成10进制数
  len=strlen(str);
  if(symm(str,0,len-1)==1)
   printf("%-8ld%-10ld\n",i,i*i);
 } 
  return 0;
}
二十七、猜名次:五个学生A、B、C、D、E参加某一项比赛。甲、乙两人在猜测比赛的结果。甲猜的名次顺序为A、B、C、D、E,结果没有猜中任何一个学生的名次,也没有猜中任何一对相邻
名次(所谓一对相邻名次,是指其中一对选手在名次上邻接。例如1与2,或者2与3等)。乙猜的名次顺序为D、A、E、C、B,结果猜中了两个学生的名次,并猜对了两对学生名次是相邻的。问比赛结果如何?答案为:E、D、A、C、B。乙猜对C、B为最后两名,两对相邻为(D、A)、(C、B))。
[解]设五名选手A、B、C、D、E的编号分别为1、2、3、4、5。用五个变量c1、c2、c3、c4、c5标记第一名至第五名。算法仍用穷尽法。其中处理相邻问题用一个两位数表示,即DA、AE、EC、CB分别用41、15、53、32表示,并按两位数比较判断相邻问题。
#include "stdio.h"
int main(){
int c1,c2,c3,c4,c5,s1,s2,t;
for(c1=2;c1<=5;c1++)
for(c2=1;c2<=5;c2++)
if(c2!=2 && (c2-c1)!=1 && c2!=c1)
for(c3=1;c3<=5;c3++)
if(c3!=3 && (c3-c2)!=1 && c3!=c2 && c3!=c1)
for(c4=1;c4<=5;c4++)
if(c4!=4 &&(c4-c3)!=1 && c4!=c1 && c4!=c2 && c4!=c3)
for(c5=1;c5<=5;c5++)
if((c5-c4)!=1 && c5!=c1 && c5!=c2 && c5!=c3 && c5!=c4){
s2=0;
if(c1==4) s2++;
if(c2==1) s2++;
if(c3==5) s2++;
if(c4==3) s2++;
if(c5==2) s2++;
s1=0;
t=10*c1+c2;
if (t==41 || t==15 || t==53 || t==32) s1++;
t=10*c2+c3;
if (t==41 || t==15 || t==53 || t==32) s1++;
t=10*c3+c4;
if (t==41 || t==15 || t==53 || t==32) s1++;
t=10*c4+c5;
if (t==41 || t==15 || t==53 || t==32) s1++;
if (s1==2 && s2==2)
printf("%3d%3d%3d%3d%3d\n",c1,c2,c3,c4,c5);
}
return 0;
}
二十八、填自然数:设有如图所示的3n+2个球互连,将自然数1-3n+2分别为这些球编号,使如图相连的球编号之差的绝对正好是数列1,2,……,3n+2中各数。
②─⑥ ②─⑨─⑤ ②─⑿─⑤─⑨
│ │ │ │ │ │ │ │ │
①─⑧─④─⑤ ①─⑾─④─⑧─⑦ ①─⒁─④─⑾─⑦─⑧
│ │ │ │ │ │ │ │ │
③─⑦ (n=2) ③─⑩─⑥ (n=3) ③─⒀─⑥─⑩ (n=4)
[解]填自然数的一种算法是:
(1)先自左向右,第1列中间1个填数,然后第2列上、下2个填数,每次2列;但若n是奇数,最后1次只排第1列中间1个数。
(2)自右向左,先右第1列中间填数;若n是奇数,再右第2列中间填数。然后依次右第1列上、下2个填数,再右第2列中间1个填数,直到左第2列为止。
[程序]
#include "stdio.h"
int main(){
const SIZE=25;
int a[3][SIZE];
int i,k,m,n;
printf("Input then n:");
scanf("%d",&n);
k=1;
for(i=0;i<=n/2;i++){
a[1][2*i]=k++;
if(i==n/2 && n%2==1 || i<n/2){
a[0][2*i+1]=k++;
a[2][2*i+1]=k++;
}
}
if(n%2==1){
a[1][n+1]=k++;
m=n;
}
else m=n+1;
for (i=0;i<=n/2;i++){
a[1][m-2*i]=k++;
if(i==n/2 && n%2==1 || i<n/2){
a[0][m-2*i-1]=k++;
a[2][m-2*i-1]=k++;
}
}
printf(" ");
for (i=1;i<=n;i++)
printf("%3d",a[0][i]);
printf("\n");
for (i=0;i<=n+1;i++)
printf("%3d",a[1][i]);
printf("\n");
printf(" ");
for (i=1;i<=n;i++)
printf("%3d",a[2][i]);
printf("\n");
return 0;
}
二十九、取数列:取{2的m次方 ,3的n次方|m>=1,n>=1}中由小到大排列的前70项数。
[解]这个数的集合事实上存在两个数列:一个是2的m次方 ,另一个是3的n次方 。若依次从两数列中取出小的进入新的数列,该新数列便为所求(这里不用数组,而直接打印输出)。
[程序]
#include "stdio.h"
#include "stdlib.h"
int main(void){
const n=70;
long double m2,n3;
int k;
char str[20];
FILE *fp;
fp=fopen("D:\\exmn.txt","w+"); //以读写方式打开文件,若文件不存在则新建文件
if(fp==NULL){
perror("文件打开失败!");
exit(0); //打开失败,把0数值返回并退出程序
}
m2=2;n3=3;k=0;
while(k<n){
if(m2<n3){
//gcvt(m2,18,str); //把双精度浮点数转换为字符串(带“.”号),最大转换成18个字符的字符串
//fprintf(fp,"%s ",str);// 以字符串形式写入文件
fprintf(fp,"%.0lf ",m2); //此句可用以上两句代替
m2*=2;
}
else{
//gcvt(n3,18,str); //同上
//fprintf(fp,"%s ",str);//同上
fprintf(fp,"%.0lf ",n3); //同上
n3*=3;
}
k++;
}
fclose(fp);
return 0;
}
三十、计算合数:一个整数n(n<=100)可以有多种分划,使其分划的一列整数之和为n。例如:
输入:n=6
输出文件hs.out,格式内容为
6
5 1
4 2
4 1 1
3 3
3 2 1
3 1 1 1
2 2 2
2 2 1 1
2 1 1 1
1 1 1 1 1 1
total=11 {表示分划数有11种}
[解]采用递归算法。从最大合数开始分划,若当前分划数之和仍不大于n,则继续分解。否则回溯再寻找分划。
[程序]
#include "stdio.h"
#include "memory.h"
int n[101], k, m, t;
FILE *f;
void output_sum(){
int j;
t++;
j = 0;
while(n[j] != 0){ //输出所有不为的合数
fprintf(f,"%3d", n[j++]);}
fprintf(f,"\n");
}
void sum(int i){
if(m-n[i] <= n[i]){ //整数分解后的余数不大于已分解的合数
n[i+1] = m - n[i]; m -= n[i++]; n[i+1] = 0;}
else { //整数分解后的余数大于已分解的合数
n[i+1] = n[i]; m -= n[i++];}
if(m != n[i]) sum(i); //未分解完继续分解
else output_sum(); //输出合数
if(n[i] > 1){ //若合数大于1可继续分解,否则回溯寻找大于1的合数
n[i]--; sum(i);}
else {
while(n[i] == 1 && i > 0){
m += n[--i];}
if(i != 0) { //找到大于1的合数,则继续分解
n[i]--; sum(i);}
}
}
int main(){
printf("Input a number:");
scanf("%d",&n[0]);
f=fopen("D:\\hs.out","w+");
t = 0;
m = n[0];
k = n[0]; //第1个合数设为要分解的数
int *np=n;
memset(np+1,0,k-1); //除第1个合数外所有合数初值均为0,内存块初始化
output_sum(); //输出第1次分解的合数
while((n[0]--) != 1){ //第1个合数不为1,则继续分解寻找合数
sum(0);
m = k;
}
fprintf(f,"total = %d\n\n\n",t);
fclose(f);
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值