1) 题目
整数划分
时间限制:3000 ms | 内存限制:65535 KB
难度:3
描述
将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,
其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表示称为正整数n的划分。求正整数n的不
同划分个数。
例如正整数6有如下11种不同的划分:
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+1。
输入
第一行是测试数据的数目M(1<=M<=10)。以下每行均包含一个整数n(1<=n<=10)。
输出
输出每组测试数据有多少种分法。
样例输入
1
6
样例输出
11
2) 题意
不再赘述。
3) 数据范围
测试数据数和n的值最大为10,数据量很小,手算都很容易。
4) 算法
搜索法
为了避免搜索到重复的划分方法,规定:
划分序列a1+a2+…+an,ai>=ai+1, 1<=i<n。
如下图是划分整数6的一棵搜索树。两方格内的数字是划分出的两个数。如6可以划分为5+1,4+2,3+3。
图中以红色数字为根节点一棵树,即为该红色数字的划分搜索树。
5) 代码
#include <iostream> #include <cstdio> #include <ctime> using namespace std; int count; //num为要划分的数,minn为允许划分出的最小数 void Backtrack(int num, int minn) { //printf("%d %d\n", num, minn); count++; if (num > 1) { int left, right; for (left = num-minn, right = minn; left >= right; left--, right++) { Backtrack(left, right); } } } int main(void) { int ncases; scanf("%d", &ncases); while (ncases-- != 0) { int num; scanf("%d", &num); count = 0; //clock_t start, finish; //start = clock(); Backtrack(num, 1); //finish = clock(); //printf("%lf\n", (double)(finish - start) / CLOCKS_PER_SEC); printf("%d\n", count); } return 0; } /* #include<iostream> using namespace std; 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 a; cin>>a; while(a--) { int n; cin>>n; cout<<q(n,n)<<endl; } return 0; } */
6) 测试数据
10
1
2
3
4
5
6
7
8
9
7) 提交结果
第一次,没有按输入格式来,粗心。