/*======================================================================= 3253:集合的划分 总时间限制: 1000ms 内存限制: 65536kB 描述 把一个集A(本题中的集合均不含重复元素)分成若干个非空子集,使得A中每个元素属于 且仅属于一个子集,那么这些子集构成的集合称为A的一个划分。 比如A={1,2,3},那么{ {1},{2 ,3} }以及{ {1},{2},{3} } 都是A的划分。 现在给定一个整数n,我们希望知道包含n个元素的集合有多少不同的划分。 当n=3的时候,仍然考虑集合{1,2,3},它的所有划分如下 { {1} , {2} , {3} } { {1 , 2} , {3} } { {1 , 3} , {2} } { {1} , {2 , 3} } { {1 , 2 , 3} } 只有5种,但随n的增加,划分方法的个数会以指数速度增加。 比如n=4的时候,就有15种方法,考虑集合{1,2,3,4},划分方式如下 { {1},{2},{3},{4}} {{1},{2},{3,4}} {{1,2},{3},{4}} {{1,3},{2},{4}} {{1,4},{2},{3}} {{1},{2,3},{4}} {{1},{3},{2,4}} {{1,2},{3,4}} {{1,3},{2,4}} {{1,4},{2,3}} {{1},{2,3,4}} {{2},{1,3,4}} {{3},{1,2,4}} {{4},{1,2,3}} {{1,2,3,4}} 当n>15的时候,划分方法数将超过32位整数所能表示的范围,我们希望你的程序能计算出 n<=15的时候,包含n个元素的集合的划分方法的个数 输入 一个整数n(0<=n<=15,n=0的时候认为有一种划分方法) 输出 包含n个不同元素的集合的划分方法的个数 样例输入 3 15 样例输出 5 1382958545 提示 递归公式, 设n个元素的集合可以划分为F(n,m)个不同的由m个非空子集组成的集合。 F(n,m) = 1, where n=0, n=m, n=1, or m=1 F(n,m) = 0, where n<m 否则 F(n,m)=F(n-1,m-1)+m*F(n-1,m) 例如: 考虑3个元素的集合,可划分为 ① 1个子集的集合:{{1,2,3}} ② 2个子集的集合:{{1,2},{3}},{{1,3},{2}},{{2,3},{1}} ③ 3个子集的集合:{{1},{2},{3}} ∴F(3,1)=1;F(3,2)=3;F(3,3)=1; 如果要求F(4,2)该怎么办呢? A.往①里添一个元素{4},得到{{1,2,3},{4}} B.往②里的任意一个子集添一个4,得到 {{1,2,4},{3}},{{1,2},{3,4}}, {{1,3,4},{2}},{{1,3},{2,4}}, {{2,3,4},{1}},{{2,3},{1,4}} ∴F(4,2)=F(3,1)+2*F(3,2)=1+2*3=7 来源:http://bailian.openjudge.cn/practice/3253/ =========================================================================*/
1 #include <stdio.h> 2 long long fun(int n,int m) 3 { 4 if(n<m) return 0; 5 else if(n==0||n==m||n==1||m==1) return 1; 6 else return fun(n-1,m-1)+m*fun(n-1,m); 7 } 8 int main(int argc, char *argv[]) 9 { 10 int n,i; 11 long long ans; 12 while(scanf("%d",&n)!=EOF) 13 { 14 ans=0; 15 if(n==0) ans=1; 16 for(i=1;i<=n;i++) 17 { 18 ans=ans+fun(n,i); 19 } 20 printf("%lld\n",ans); 21 } 22 return 0; 23 }
题目链接:http://bailian.openjudge.cn/practice/3253/
时间: 2024-10-12 02:12:27