十六、齿轮重遇问题:三个齿轮啮合。在齿轮箱里三个齿轮相互衔接,某瞬间两对齿相遇。问各转多少圈后,这两对齿再次重逢。(说明:用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;
}