2024年春季学期《算法分析与设计》练习3

目录

问题 A: 判断是否为2的幂

问题 B: 递归求和

问题 C: 汉诺塔II

问题 D: 九数组分数

问题 E: 数的划分 

问题 F: 字母全排列 


问题 A: 判断是否为2的幂

题目描述

给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 0 ;否则,返回 1 。
如果存在一个整数 x 使得n == 2x ,则认为 n 是 2 的幂次方。
请用递归编写一个程序来判断。【友情提醒:请使用递归来实现】

输入

多组输入,每组输入一个非负整数,每组占一行

输出

输出结果,每个结果占一行

样例输入 

1
16
3
4
5

样例输出 

0
0
1
0
1
#include <stdio.h>
int fun(int n){
	if(n<=0) return 1;
	if(n==1) return 0;
	if(n&1) return 1;
	else return fun(n/2);
}
int main(){
    int n,x;
	while(scanf("%d",&n)!=EOF){
		if(fun(n)==0)
			printf("0\n");
		else
			printf("1\n");
	}
}

 问题 B: 递归求和

题目描述

使用递归编写一个程序,求:
S(n)=1-1/2+1/3-1/4+1/5-1/6+......

输入

多组数据输入,每组输入一个正整数n。

输出

输出S(n)的计算结果(精确到小数点后六位)。

样例输入 

1

样例输出 

1.000000
#include <stdio.h>
double fun(int n){
	 if (n == 0) {
        return 0.0;
    }
	double x=((n%2==0) ? -1.0:1.0)/n;
	return fun(n-1)+x;
	
}
int main(){
    int n;
	double x;
	while(scanf("%d",&n)!=EOF){
		x=fun(n);
		printf("%.6f\n",fun(n));
		x=0;
	}
}

 问题 C: 汉诺塔II

题目描述
用1,2,...,n表示n个盘子,称为1号盘,2号盘,...。号数大盘子就大。经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。我们知道最少需要移动2^64-1次.在移动过程中发现,有的圆盘移动次数多,有的少 。 告之盘子总数和盘号,计算该盘子的移动次数.


输入
包含多组数据,首先输入T,表示有T组数据.每个数据一行,是盘子的数目N(1<=N<=60)和盘号k(1<=k<=N)。


输出
对于每组数据,输出一个数,到达目标时k号盘需要的最少移动数。


样例输入
2
60 1
3 1


样例输出 
576460752303423488
4

#include <stdio.h>

int main(){
    int n,t,k,i;
	long long x=1;
	
	while(scanf("%d",&t)!=EOF){
		while(t--){
			scanf("%d%d",&n,&k);
			for(i=1;i<=n-k;i++){
				x*=2;
			}
			printf("%lld\n",x);
			x=1;
		}
	}
}

 问题 D: 九数组分数

题目描述
1, 2, 3...9 这九个数字组成一个分数,其值恰好为1/3,要求每个数字出现且只能出现一次,如何组合?编写程序输出所有的组合。


输入


输出
输出所有的结果,如果有多个,每条结果占一行。
结果的格式 : xxxx/xxxxx ,按照分子从小到大的顺序输出。

#include <stdio.h>  
  
void swap(int *a, int *b) {  
    int temp = *a;  
    *a = *b;  
    *b = temp;  
}  
  
void t(int a[], int k, int m) {  
    if (m == k) {  
        int x = a[1] * 1000 + a[2] * 100 + a[3] * 10 + a[4];  
        int y = a[5] * 10000 + a[6] * 1000 + a[7] * 100 + a[8] * 10 + a[9];  
        if (x * 3 == y) {  
            for (int i = 1; i <= 9; i++) {  
                printf("%d", a[i]);  
                if (i == 4) {  
                    printf("/");  
                }  
            }  
            printf("\n");  
        }  
    }  
    for (int i = m; i >= k; i--) {  
        swap(&a[m], &a[i]);  
        t(a, k, m - 1);  
        swap(&a[m], &a[i]);
    }  
}  
  
int main() {  
    int a[10];  
    for (int i = 0; i < 9; i++) {  
        a[i + 1] = i + 1;  
    }  
    t(a, 1, 9);  
    return 0;  
}

问题 E: 数的划分 

题目描述
使用递归编写一个程序,求一个正整数n的所有划分个数。
例如,输入3,输出3;输入4,输出5。


输入
多组输入,每一组是一个正整数n。


输出
输出划分数。


样例输入
3
4


样例输出 
3
5

#include <stdio.h>  

int q(int n,int m){
	if((n<1)||(m<1)) return 0;
	if((n==1)||(m==1)) return 1;
	if(n<m) return q(n,n);
	if(n==m) return q(n,m-1)+1;
	return q(n,m-1)+q(n-m,m);
}
  
int main(){  
	int n,s;
	while(scanf("%d",&n)!=EOF){
		s=q(n,n);
		printf("%d\n",s);
	}
    return 0;  
}

问题 F: 字母全排列 

题目描述
编写一个程序,使用递归算法输出一个一维字符数组中所有字符的全排列,假设字符都不一样。例如{'a','b','c'}的全排列为(a,b,c), (a,c,b), (b,a,c), (b,c,a), (c,a,b), (c,b,a)


输入
多组测试用例,每组输入一个正整数n(0<n<=26)。


输出
输出从a开始,连续n个字母的全排列,且每组输出之间用空格隔开。


样例输入 
1
2


样例输出
a

ab
ba

#include <stdio.h>  
#include <stdlib.h>  
  
#define max 26  
  
	int a[max],n;  
	char b[max];   
  
void fun(int x) {  
    if (x == n) {  
        for (int i = 0; i < n; i++) {  
            printf("%c", b[i]);  
        }  
        printf("\n");  
        return;  
    }  
    for (int i = 0; i < n; i++) {  
        if (a[i] == 0) {  
            b[x] = 'a' + i;  
            a[i] = 1;  
            fun(x + 1);  
            a[i] = 0;  
        }  
    }  
}  
  
int main() {  
    while (scanf("%d", &n) != EOF) {  
        for (int i = 0; i < n; i++) {  
            a[i] = 0;  
        }  
        fun(0);  
        printf("\n");  
    }  
    return 0;  
}

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值