【NOI联考by ysy】庆典
2016年6月17日1,1040
【题目描述】
战狂在昌和帝国的首都法法城召开了庆典,向一万名最杰出的士兵分发了用魔法猪做的猪肉饺子,士兵们吃了猪肉饺子后,战斗力大幅提高。
为了保护战狂的安全以及维护现场秩序,大预言家抽调了n名普通士兵组成了m个小队完成一些不同的任务。由于一些特殊的原因,所有小队的人数都互不相同。
你需要求出有多少种可能的组队方案。注意士兵是相同的,而小队是不同的。
【输入数据】
第一行两个个整数n,m。
【输出数据】
一行一个数表示答案。对998244353取模。
【样例输入】
16 4
【样例输出】
216
【数据范围】
对于20%的数据,n,m<=20。
对于50%的数据,n,m<=3000。
对于100%的数据,n,m<=100000。
这个题目就比较简单
首先所有小队的人都不相同
那就先给每个位置(i)分配(i)个队员
对于剩下的人就分配给这m个小队
所以就(O(nm))递推
这个递推有点熟悉(整数拆分问题)
递推法
根据n和m的关系,考虑下面几种情况:
(1)当n=1时,不论m的值为多少(m>0),只有一种划分,即({1});
(2)当m=1时,不论 的值为多少(n>0),只有一种划分,即({1,1,....1,1,1});
(3)当n=m时,根据划分中是否包含n,可以分为两种情况:
(a)划分中包含n的情况,只有一个,即({n});
(b)划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有((n-1))划分;
因此,(f(n,n)=1+f(n, n-1))。
(4)当n时,由于划分中不可能出现负数,因此就相当于f(n,n);
(5)当n>m时,根据划分中是否包含m,可以分为两种情况:
(a)划分中包含 的情况,即{m,{x1,x2,x3,...,xi}},其中{x1,x2,x3,...,xi}的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分个数为f(n-m,m;
(b)划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1;
因此,f(n,m)=f(n-m,m)+f(n,m-1) 。
综合以上各种情况,可以看出,上面的结论具有递归定义的特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,而情况(5)为通用情况,属于递归的方法,其本质主要是通过减少n或m以达到回归条件,从而解决问题。
详细递推公式描述如下:
那么
#include<iostream>
#include<cstdio>
#define N 100005
#define mod 998244353
using namespace std;
int dp[N];
int main(){
int n,m;
cin>>n>>m;
n-=m*(m+1)/2;
dp[0]=1;
for(int i=1;i<=m;++i)
for(int j=i;j<=n;++j)
dp[j]=(dp[j]+dp[j-i])%mod;
for(int i=2;i<=m;++i)
dp[n]=(dp[n]*i)%mod;
printf("%d",dp[n]);
return 0;
}