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 种,即初始化。

 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 }
View Code