主要内容 #
- 分解因数
- 放苹果问题
1. 分解因数 #
问题描述
给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * … * an,并且1 < a1 <= a2 <= a3 <= … <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。
输入
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768)。
输出
n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数。
样例输入
2
2
20
样例输出
1
4
算法分析 #
令i = 2~an,通过an%i ==0来判断i是不是an的因数,如果是,则由an/i作为参数进一步带入函数来判断直至an/i == i,(此时i为最后一个因数)。
首先需知道f(m,n)的含义——求n中从m开始到n/m所有分解种数的和。而为什么每次只要满足上面的条件就算加一种情况呢?这不妨举个例子当n = 100时,2、50算一种情况,而50可以继续分为2、25,这就有了2、2、25,再继续分,且每次分都能成为其一种分解情况所以a++。
参考程序 #
#include < iostream > using namespace std; int s = 0; //s用来记录分解的种类的数 void f(int x, int y) //x为因数,y为被分解数 { for (int i = x; i * i >= y; ++i) {//依次试每一次分解 if (y % i == 0) { ++s;//种数加一 f(i, y / i);//返回下一次函数调用 } } } int main() { int t; cin >> t; //输入样例的总数 while (t--) { int a = 0; cin >> a; s = 1;//a=a也算一种分解 f(2, a); cout << s << endl; } return 0; }
2. 放苹果问题 #
问题描述
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?5,1,1和1,5,1 是同一种分法。
输入
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
输出
对输入的每组数据M和N,用一行输出相应的K。
样例输入
1
7 3
样例输出
8
算法分析 #
该题目主要运用了递推的思维方式,解决的关键在于找出递推关系和递推出口。
m个苹果放在n个盘子中,设递推函数为apple(m,n):
情况1:
m=0,没有一个苹果,则apple(0,n)=1;
情况2:
n=1,只有一个盘子,则apple(m,1)=1
情况3:
n>m,与m个苹果放在m个盘子中情况一样,则apple(m,n)=m
情况4:
n<=m,按是否有空盘子,又可以分为两种情况:
则有以下递推关系:apple(m,n)=apple(m−n,n)+apple(m,n−1)
综上所述:可以将情况1和情况2视为一种临界条件,即为n=1时,所有苹果都在一个盘子中;m=0时,没有苹果可放!这种临界条件通常可以视为递归出口。
参考程序 #
#include < iostream > using namespace std; int apple(int m,int n) { //情况1和情况2 if(m<=1||n==1) return 1; //情况3 if(n>m) return apple(m,m); else return(apple(m-n,n)+apple(m,n-1)); //情况4 } int main() { //设置两个数组分别存苹果数和盘子数 int n,a[20],b[20],i; cin>>n; for(i=0;i < n;i++) cin>>a[i]>>b[i]; for(i=0;i < n;i++) { cout << apple(a[i],b[i]) << endl; } return 0; }