BC # 32 1004
题意:要求 n 个数和为 n ,而且后一个数等于前一个数或者等于前一个数加 1 ,问有多少种组合。
其实是一道很水的完全背包,但是没有了 dp 的分类我几乎没有往这边细想,又是放在第四题,因此完全没有想出来。
其实并不难,dp [ i ] [ j ] 表示当前放入 i ,总和是 j 的种类数
dp [ i ] [ j ] = dp [ i - 1 ] [ j - i ] + dp [ i ] [ j - i ] ;即上一个放的是 i 或 i - 1 ;
dp [ 0 ] [ 0 ] = 1 表示不放数字和为 0 种类数为 1 种,即初始化。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h>
2 #include<string.h>
3 #include<math.h>
4 #define ll long long
5 #define max(a,b) a>b?a:b
6
7 int dp[320][50005];
8
9 int main(){
10 int T;
11 while(scanf("%d",&T)!=EOF){
12 for(int q=1;q<=T;q++){
13 int n,mod,ans=0;
14 scanf("%d%d",&n,&mod);
15 memset(dp,0,sizeof(dp));
16 int m=(sqrt(8.0*n+1)-1)/2;
17 int i,j;
18 // printf("%d\n",m);
19 dp[0][0]=1;
20 for(i=1;i<=m;i++){
21 for(j=0;j<=n;j++){
22 if(i>j)dp[i][j]=0;
23 else dp[i][j]=(dp[i-1][j-i]+dp[i][j-i])%mod;
24 if(j==n)ans=(ans+dp[i][j])%mod;
25 }
26 }/*
27 for(i=0;i<=m;i++){
28 for(j=0;j<=n;j++){
29 printf("%3d",dp[i][j]);
30 }
31 printf("\n");
32 }*/
33 printf("Case #%d: %d\n",q,ans);
34 }
35 }
36 return 0;
37 }