算法设计与分析实验1

一、统计数字问题

题目描述

问题描述
一本书的页码从自然数 1 开始顺序编码直到自然数 n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字 0。例如,第 6 页用数字 6 表示,而不是 06 或 006 等。数字计数问题要求对给定书的总页码 n,计算出书的全部页码中分别用到多少次数字 0,1,2,…,9

编程任务:
给定表示书的总页码的 10 进制整数 n (1≤n≤109) 。编程计算书的全部页码中分别用到多少次数字 0,1,2,…,9。

输入
给出表示书的总页码的整数 n

输出
输出共有10行,在第 k 行输出页码中用到数字 k-1 的次数,k=1,2,…,10。

样例输入
11
样例输出
1
4
1
1
1
1
1
1
1
1

代码

#include<iostream>
using namespace std;
int a[10];
void tongji(int x) { //从后往前进行除余
	int weishu = 10;
	for (int i = 0; i <= x; i++) {
		int tmp = i;
		while (10*tmp >= weishu) {
				a[tmp % 10]++;//数位上数字出现次数加1
				tmp /= 10;//分析下一位
			}
	}
	
}
int main() {
	int n;
	cin >> n;
	
	tongji(n);
	for (int i = 0; i < 10; i++) {
		cout << a[i] << endl;
	}
	return 0;
}

二、字典序

题目描述

在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表 A 由 26 个小写英文字母组成 A={a,b,…,z}。该字母表产生的升序字符串是指字符串中字母按照从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现 1 次。例如,a,b,ab,bc,xyz 等字符串都是升序字符串。现在对字母表 A 产生的所有长度不超过 6 的升序字符串按照字典序排列并编码如下。
1 2 … 26 27 28 …
a b … z ab ac …
对于任意长度不超过 6 的升序字符串,迅速计算出它在上述字典中的编码
文件的第一行是一个正整数 k,表示接下来共有 k 行。
接下来的 k 行中,每行给出一个字符串。

输出
运行结束输出共有 k 行,每行对应于一个字符串的编码

样例输入
2
a
b
样例输出
1
2

代码

#include<iostream>
#include<string>
using namespace std;
int c(int n, int m) {//求出长度为m的所有组合个数
	int m_n=1;
	int m_=1;
	for (int i = n - m + 1; i <= n; i++) {
		m_n *= i;
	}
	for (int i = 1; i <= m; i++) {
		m_ *= i;
	}
	return m_n/m_;
}
int num(string s,int i ) {//i为当前首字母前的字母个数,这些字母不能取用
	//递归求该组合前长度为n的字符串个数
	int sum = 0;
	int len = s.length();
	if (len < 1)return 0;
	char ch = s[0];//获得首字母
	for (int k = 1; k <= ch - 'a'-i; k++) {//第二位取首位前,上一个首位后的字母[上一个首位,当前首位]
		sum += c(26 - k-i, len - 1);//计算首字母后续字母组合,k为已取字母
	}
	if (len > 1)
		sum += num(&s[1],ch-'a'+1);//当首字母和所求字符串首字母一样时,看下一位
	return sum;
}

int main() {
	int n;
	cin >> n;
	string s;
	for (int i = 0; i < n; i++) {
		cin >> s;
		int len = s.length();
		int sum = 0;//sum表示序列数,序列数=长度len-1字母随机排序和+该组合前长度为len的组合数+1
		for (int j = 1; j < len;j++) {
			sum += c(26, j);
		}
		sum += num(s,0);
		cout<<sum+1 <<endl;
	}

	return 0;
}

三、最多约数问题

问题描述:

正整数 x 的约数是能整除 x 的正整数。正整数 x 的约数个数记为 div(x)。例如,1,2,5,10 都是正整数10 的约数,且 div(10)=4。设 a 和 b 是 2 个正整数,a≤b,找出 a 和 b之间约数个数最多的数 x。
编程任务:
对于给定的 2 个正整数 a≤b,编程计算 a 和 b 之间约数个数最多的数。
输入
第1 行有 2 个正整数 a 和 b。
输出
若找到的 a 和 b 之间约数个数最多的数是 x,将 div(x)输出
样例输入
1 36
样例输出
9
提示
输入范围:1-1000000000

代码


#include<iostream>
using namespace std;
int a, b;
int maxn;
int div(int x) {
	int m=0;//m表示每个数的约数
	for (int i = 1; i * i <= x; i++) {//[ 1, x^(1/2) )范围内x可约时m+=2
		if (x % i == 0) 
			if (i * i == x)//约数为根号x时m+=1
				m++;
			else m+=2;
		}
	}
	return m;
}
int main() {
	cin >> a >> b;//输入范围[a,b]
	for (int i = a; i <= b; i++) {
		int divi = div(i);//对每一个输入的数求约数
		if (maxn < divi)
			maxn = divi;
	}
	cout << maxn;
	return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值