P1287 盒子与球

题解 - P1287

题目描述

题目传送门

S o l \mathrm{Sol} Sol

  • 暴力 D P DP DP

我们考虑设 f i , j f_{i,j} fi,j 表示到第 i i i 个球放入 j j j 个盒子里的方案数。

考虑如何转移,莫过于两种情况:放入原有的盒子,重新开一个盒子。

对于第一种情况 f i , j = f i − 1 , j × j f_{i,j}=f_{i-1,j}\times j fi,j=fi1,j×j 即在原有的箱子中选一个

对于第二种情况 f i , j = f i − 1 , j − 1 × ( m − j + 1 ) f_{i,j}=f_{i-1,j-1}\times (m-j+1) fi,j=fi1,j1×(mj+1) 即在没选的 m − j + 1 m-j+1 mj+1 个盒子里选择一个放入

以及注意枚举 j j j 的下界为 m − n + i m-n+i mn+i 因为要保证盒子非空。

最后答案即 f n , m f_{n,m} fn,m

C o d e \mathrm{Code} Code

#pragma GCC optimize(3,"Ofast","inline")
#include 
#define For(i,a,b) for ( register int i=(a);i<=(b);i++ )
#define Dow(i,b,a) for ( register int i=(b);i>=(a);i-- )
#define GO(i,x) for ( int i=head[x];i;i=e[i].nex )
#define mem(x,s) memset(x,s,sizeof(x))
#define cpy(x,s) memcpy(x,s,sizeof(x))
#define YES return puts("YES"),0
#define NO return puts("NO"),0
#define GG return puts("-1"),0
#define pb push_back
#define lowbit(x) x&(-x)
using namespace std;

inline int read()
{
	int sum=0; char ch=getchar();
	while(!isdigit(ch))
		ch=getchar();
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum;
}

const int mod=1e9+7;
const int mo=998244353;
const int N=1e6+5;
const int M=1005;

inline int min(int x,int y) {if(x<y) return x; return y;}
inline int max(int x,int y) {if(x>y) return x; return y;}

int n,m,f[11][11],ans;

int main()
{
	n=read(),m=read();
	f[0][0]=1;
	For(i,1,n) For(j,max(0,m-n+i),m) 
	f[i][j]=(f[i][j]+f[i-1][j-1]*(m-j+1)+f[i-1][j]*j);
	printf("%d\n",f[n][m]);
	return 0;
}
			
	

你可能感兴趣的:(DP)