4 1 2 3 100
1 2 5 751
n个卡,最多能放在n个书里边,最少能放在1本书里边,我们规定S(n,k)表示n个卡放在k本书里边有多少种方法。
这里ans【n】=S(n,1)+S(n,2)+.......................+S(n,n);
我们知道,S(n,1)=1;S(n,n)=1;
特殊讨论S(n,k)【其中k从2到n-1】;
一共有两种可能性:
我们从n个卡里边随便拿出一个卡来,这个时候卡分成两部分,一部分是n-1,一部分是1、对于这个1进行讨论有两种可能:
1、单独分在一本书里边,n-1那部分分在k-1本书里边,这个情况表示为S(N-1,k-1);
2、跟n-1本书放在一起(放在k本书里边),S(n-1,k),因为这个卡有K种放置方法。所以表示为K*S(n-1,k);
即其动态转移方程为:
S(n,k)【2<=k<=n-1】=S(n-1,k-1)+k*S(n-1,k);
对应写出代码。求余部分不要忘记:
#include<stdio.h> #include<string.h> using namespace std; #define mod 1000 int dp[2002][2002]; int ans[2002]; int main() { memset(dp,0,sizeof(dp)); for(int i=1;i<=2000;i++) { dp[i][0]=0; dp[i][i]=1; for(int j=1;j<i;j++) { dp[i][j]=(dp[i-1][j-1]+j*dp[i-1][j])%mod; } } for(int i=1;i<=2000;i++) { ans[i]=0; for(int j=1;j<=i;j++) { ans[i]=(ans[i]+dp[i][j])%mod; } } int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); printf("%d\n",ans[n]); } }