组合数学持续更新

poj 1664 放苹果

http://poj.org/problem?id=1664

一道基础的题目,dp[i][j]代表 i 个苹果 放到 j 个盘子的总类数目。

dp[ i ][ j ] = dp[ i ] [j -1 ] + dp[ i -j ][ j ];

分类讨论第j个盘子是否放了苹果。

没有放的时候 dp [ i ][ j-1 ]种,把i个苹果全部放在前 j -1 个盘子里;

放的时候,可能是放一个,可能是放多个,也就说我可以这样转化,先在所有的盘子上放上一个,然后,任意放。

即dp[ i - j ] [ j ].

 1 #include<stdio.h>
 2 
 3 int dp[11][11];
 4 void prepare()
 5 {
 6     int i,j;
 7     // put i apples into j pans.
 8     
 9     for(i=0;i<=10;i++) dp[0][i]=1;
10     for(i=1;i<=10;i++)
11     {
12         for(j=1;j<=10;j++)
13             if(j<=i)
14                 dp[i][j]=dp[i][j-1]+dp[i-j][j];
15             else 
16                 dp[i][j]=dp[i][j-1];
17     }
18 }
19 int main()
20 {
21     int T;
22     int n,m;
23     prepare();
24     scanf("%d",&T);
25     while(T--)
26     {
27         scanf("%d%d",&n,&m);
28         printf("%d\n",dp[n][m]);
29     }
30     return 0;
31 }
View Code

 

 hdu 2512

一卡通大冒险

也是一道基础的题目。

dp[ i ] [ j ] 代表 i 个东西分成 j 个集合的方法数。

也对第j 个元素进行讨论。

dp[ i ] [j ] = dp [ i -1 ] [ j -1 ] + j* dp[ i -1][ j ];

方法同上,唯一不同在于 集合中没有排序。

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 int dp[2001][2001];
 5 void prepare()
 6 {
 7     int i,j;
 8     dp[1][1]=1;
 9     for(i=2;i<=2000;i++)
10         for(j=1;j<=i;j++)
11             dp[i][j]=(dp[i-1][j-1]+j*dp[i-1][j])%1000;
12 }
13 int main()
14 {
15     int T;
16     int n,i,cur;
17     scanf("%d",&T);
18     prepare();
19     while(T--)
20     {
21         scanf("%d",&n);
22         cur=0;
23         for(i=1;i<=n;i++)
24             cur=(cur+dp[n][i])%1000;
25         printf("%d\n",cur);
26     }
27     return 0;
28 }
View Code

 java代码,第一次写java代码哈哈。

 1 //package day0;
 2 import java.util.*;
 3 
 4 public class Main {
 5     
 6     static int dp[][]= new int[2001][2001];
 7     public static void main(String[] args) {
 8         // TODO Auto-generated method stub
 9         int T,t,n,cur,i;
10         fun();
11         Scanner cin = new Scanner(System.in);
12         T = cin.nextInt();
13         for(t=1;t<=T;t++)
14         {
15             n = cin.nextInt();
16             cur = 0;
17             for(i=1;i<=n;i++)
18                 cur=(cur+dp[n][i])%1000;
19             System.out.println(cur);
20         }
21     }
22     public static void fun()
23     {
24         int i,j;
25         dp[1][1]=1;
26         for(i=2;i<=2000;i++)
27         {
28             for(j=1;j<=i;j++)
29                 dp[i][j]=(dp[i-1][j-1]+j*dp[i-1][j])%1000;
30         }
31     }
32     
33 }
View Code

 

 hdu 2085 核反应堆

 基础题

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 
 5 typedef __int64 LL;
 6 
 7 LL dp[34][2];
 8 
 9 void prepare()
10 {
11     int i,j;
12     memset(dp,0,sizeof(dp));
13     dp[0][1]=1;dp[0][0]=0;
14     dp[1][1]=3;dp[1][0]=1;
15     for(i=2;i<=33;i++)
16     {
17         dp[i][1]=3*dp[i-1][1]+2*dp[i-1][0];
18         dp[i][0]=dp[i-1][1]+dp[i-1][0];
19     }
20 }
21 int main()
22 {
23     int n;
24     prepare();
25     while(scanf("%d",&n)>0)
26     {
27         if(n==-1)break;
28         printf("%I64d, %I64d\n",dp[n][1],dp[n][0]);
29     }
30     return 0;
31 }
View Code

 

hdu 3398 String

hdu 3944 dp?

hdu 3037 Saving Beans

nyoj 光棍节的快乐 组合+错排公式

 1 /**
 2 1、当N=1和2时,易得解~,假设F(N-1)和F(N-2)已经得到,
 3    重点分析下面的情况:
 4 2、当有N封信的时候,前面N-1封信可以有N-1或者 N-2封错装
 5 3、前者,对于每种错装,可从N-1封信中任意取一封和第N封错装,
 6     故=F(N-1)*(N-1)
 7 4、后者简单,只能是没装错的那封和第N封交换信封,
 8     没装错的那封可以是前面N-1封中的任意一个,故= F(N-2) * (N-1)
 9 **/
10 #include<stdio.h>
11 typedef long long LL;
12 LL dp[21];
13 void init()
14 {
15     LL i;
16     dp[1]=0;
17     dp[2]=1;
18     for(i=3;i<=20;i++)
19         dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
20 }
21 int main()
22 {
23     init();
24     LL n,m;
25     LL i,j,sum,k;
26     while(scanf("%lld%lld",&n,&m)>0)
27     {
28         k=m;
29         if(m>n-m) m=n-m;
30         sum=1;
31         for(i=1,j=n;i<=m;j--,i++)
32             sum=sum*j/i;
33         printf("%lld\n",sum*dp[k]);
34     }
35     return 0;
36 }
View Code

 

 

posted @ 2014-04-09 16:57  芷水  阅读(265)  评论(0编辑  收藏  举报