P1655 小朋友的球

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 #1
4 2
1 1
输出 #1
7
1

说明/提示

【样例解释】

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。

算法分析

  • 简单的动态规划,但是要加上高精度运算,不然只能得 2020 分。本题和 放苹果 有些类似,但是盒子不能空着不放,也就是楼下所说的 Stirling数,应用于组合数学领域

  • 状态转移方程:f[i][j]=f[i-1][j-1]+f[i-1][j] imes jf[i][j]=f[i1][j1]+f[i1][j]×j

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 999999999
#define For(i,a,b) for(i=a;i<=b;++i)
#define rep(i,a,b) for(i=a;i>=b;--i)
#define mm(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
ll read(){
    ll sum=0,flag=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    while(c>='0'&&c<='9')sum=sum*10+c-'0',c=getchar();
    return sum*flag;
}
ll maxx(ll x,ll y){
    if(x<y)return y;
    return x;
}
ll minn(ll x,ll y){
    if(x<y)return x;
    return y;
}
ll abss(ll x){
    if(x>=0)return x;
    return -x;
}
struct node{
    ll a[500],len;
    node(){mm(a,0);len=0;}//记得初始化
};
node t[111][111];
node operator + (node c,node d){
    node h;h.len=maxx(c.len,d.len);
    int i;
    for(i=1;i<=h.len;i++){
        h.a[i]+=c.a[i]+d.a[i];
        if(h.a[i]>=10){
            h.a[i+1]+=h.a[i]/10;
            h.a[i]%=10;
            if(i==h.len)h.len++;
        }
    }
    return h;
}
node operator * (node c,ll u){
    node h;h.len=c.len;
    int i;
    for(i=1;i<=h.len;i++){
        h.a[i]+=c.a[i]*u;
        if(h.a[i]>=10){
            h.a[i+1]+=h.a[i]/10;
            h.a[i]%=10;
            if(i==h.len)h.len++;
        }
    }
    return h;
}
int main(){
    ll i,j,m,n;
    For(i,1,100)t[i][0].a[1]=0,t[i][i].a[1]=t[i][1].a[1]=1,t[i][0].len=t[i][i].len=t[i][1].len=1;
    For(i,2,100){
        For(j,2,i-1){
            t[i][j]=t[i-1][j-1]+t[i-1][j]*j;
        }
    }
    while(scanf("%lld%lld",&m,&n)!=EOF){
        if(n==0||n>m){printf("0
");continue;}
        rep(i,t[m][n].len,1)printf("%lld",t[m][n].a[i]);
        printf("
");
    }    
    return 0;
}
原文地址:https://www.cnblogs.com/hrj1/p/11749960.html