斯特林数

来源:互联网 发布:网络pc蛋蛋赌博定罪 编辑:程序博客网 时间:2024/05/21 04:23

洛谷P1655 小朋友的球

题目描述

@发源于 小朋友最近特别喜欢球。有一天他脑子抽了,从口袋里拿出了N个不同的球,想把它们放到M个相同的盒子里,并且要求每个盒子中至少要有一个球,他好奇有几种放法,于是尝试编程实现,但由于他天天不好好学习,只会上B站看游泳教练,于是他向你求助。

输入输出格式

输入格式:

多组数据,每行两个数N,M。

输出格式:

每组数据一行,表示方案数。

输入输出样例

输入样例#1:
4 21 1
输出样例#1:
71

说明

【样例解释】

N=4,M=2

1,2 3 4

2,1 3 4

3,1 2 4

4,1 2 3

1 2,3 4

1 3,2 4

1 4,2 3

对于20%的数据,满足1≤N,M≤10;

对于100%的数据,满足1≤N,M≤100,数据组数≤10。



stirling数

斯特林数解决的是这样一个问题:
n个不相同的元素,分割为m个集合,每个集合非空【至少有一个元素】,集合无序,问有多少种分割方法?
其实就是题目所述的分球问题

我们令f(n,m)为答案,根据dp的思想,对于第i个球,要么单独放一个盒子,要么在前i-1个球放完后加入其中一个盒子
那么就有f(n,m)=f(n-1,m-1)+j*f(n-1,m)
边界f(i,i)=1,i>=0
f(i,0)=0,i>=1
那么加上高精度就可以解了


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#define LL long long intusing namespace std;const int maxn=105,INF=2000000000;int N,M;class BIG{public:int n[maxn],len;BIG() {memset(n,0,sizeof(n));len=0;}}dp[maxn][maxn];istream& operator >>(istream& in,BIG& a){string s;in>>s;a.len=s.length();for(int i=0;i<a.len;i++) a.n[i]=s[a.len-i-1]-'0';return in;}ostream& operator << (ostream& out,const BIG& a){if(!a.len) cout<<0;for(int i=a.len-1;i>=0;i--) out<<a.n[i];return out;}BIG operator + (const BIG& a,const BIG& b){BIG c;c.len=max(a.len,b.len);int carry=0,temp;for(int i=0;i<c.len;i++){temp=a.n[i]+b.n[i]+carry;c.n[i]=temp%10;carry=temp/10;}if(carry) c.n[c.len++]=carry;return c;}BIG operator * (const BIG& a,const int& b){int carry=0,temp;BIG c;c.len=a.len;for(int i=0;i<a.len;i++){temp=a.n[i]*b+carry;c.n[i]=temp%10;carry=temp/10;}while(carry) c.n[c.len++]=carry%10,carry/=10;return c;}int main(){for(int i=0;i<=100;i++){dp[i][i].len=dp[i][i].n[0]=1;}for(int i=1;i<=100;i++)for(int j=1;j<=i;j++){dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1];}while(cin>>N>>M) cout<<dp[N][M]<<endl;return 0;}



原创粉丝点击