//目录

数学基础——递推关系

问题1:兔子的繁殖

一对兔子在第二个月后才能产下一对新兔子。第n个月后有多少兔子。

分析:第n个月的兔子数f(n),这f(n)个兔子可以分为两个部分,第一部分是上个月留下来的老兔子f(n-1),

和新兔子,新兔子的数目是上个月有能力生育的兔子之和,也就是n-2天的兔子都有生育能力

 

问题2:多边形的三角剖分。

给定一个凸n边形,把他分成三角形,求有多少种分法。

(和最优三角剖分类似,只不过不再是一个最值了,而是一个方案数)

 

问题3:火柴

用n个火柴可以拼成多少种不同的数字。火柴可以不必用完。

题目链接:https://uva.onlinejudge.org/external/113/11375.pdf

分析:

 1 import java.math.BigInteger;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5 
 6     Main() {
 7         int c[] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
 8         BigInteger d[] = new BigInteger[2005];
 9         BigInteger sum[] = new BigInteger[2005];
10 
11         for (int i = 0; i <= 2000; i++) {
12             d[i] = new BigInteger("0");
13             sum[i] = new BigInteger("0");
14         }
15 
16         d[0] = new BigInteger("1");
17 
18         for (int i = 0; i <= 2000; i++) {
19             for (int j = 0; j < 10; j++) {
20                 if (!(i == 0 && j == 0) && i + c[j] <= 2000) {
21                     d[i + c[j]] = d[i + c[j]].add(d[i]);
22                 }
23 
24             }
25         }
26         
27         for(int i=1;i<=2000;i++) {
28             sum[i] = sum[i].add(sum[i-1]);
29             sum[i] = sum[i].add(d[i]);
30         }
31 
32         Scanner in = new Scanner(System.in);
33         while (in.hasNextInt()) {
34             int n = in.nextInt();
35             if (n == 0)
36                 System.out.println("0");
37             else if (n < 6)
38                 System.out.println(sum[n]);
39             else {
40                 System.out.println(sum[n].add(new BigInteger("1")));
41             }
42         }
43     }
44     
45 
46     public static void main(String[] args) {
47         new Main();
48     }
49 }
View Code

 

问题4:立方数之和

题目链接:https://uva.onlinejudge.org/external/111/11137.pdf

题意:给定一个数n ,求能够写成的立方形式有多少种。

分析:

就像DP种多阶段决策一样,d(i,j),最大的元素为 i ,和为 j;题目已经给出 i <22;

那么:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int n;
 8     unsigned long long d[22][10000+5];
 9 
10 
11 
12     memset(d,0,sizeof(d));
13 
14     d[0][0] = 1;
15     for(int i=1;i<=21;i++) {
16         for(int j=0;j<=10000;j++) {
17             for(int a=0;j+a*i*i*i<=10000;a++) {
18                 d[i][j+a*i*i*i] += d[i-1][j];
19             }
20         }
21     }
22     while(cin>>n)
23         cout<<d[21][n]<<endl;
24 
25     return 0;
26 }
View Code

 

 

问题5:村民排队

题目链接:https://uva.onlinejudge.org/external/111/11174.pdf

题意:

村子里面有n个人来排队,里面有一些父子关系,儿子不能排到父亲的前面,有多少种排法?

分析:

题目肯定是一个森林,设一个超级父亲节点,他下面如上图有三个子节点,

那么排法就有:

一般的:

设节点 i 为根的子树有f(i)种排法:

 

问题6:带标号的连通图的计数;

http://oeis.org/A001187

数列如上所示:

题目链接:http://poj.org/problem?id=1737

答案是f(n),g(n) 是非联通图个数,那么就有 

g(n):先考虑1节点所在的连通分量包含哪些顶点:C(n-1,k-1);

这个连通分量有f(k),其他有h(n-k)种情况。

 1 import java.math.BigInteger;
 2 import java.util.Scanner;
 3 
 4 public class Main {
 5 
 6     Main() {
 7         BigInteger two[] = new BigInteger[5055];
 8         two[0] = BigInteger.ONE;
 9         for (int i = 1; i <= 5050; i++)
10             two[i] = two[i - 1].multiply(BigInteger.valueOf(2));
11         BigInteger h[] = new BigInteger[55];
12         for (int i = 1; i <= 50; i++) {
13             h[i] = two[i*(i-1)/2];
14         }
15         
16         BigInteger C[][] = new BigInteger[55][55];
17         C[0][0] = BigInteger.ONE;
18         for (int i = 0; i <= 50; i++) {
19             C[i][0] = C[i][i] = BigInteger.ONE;
20             for (int j = 1; j < i; j++) {
21                 C[i][j] = C[i - 1][j].add(C[i - 1][j - 1]);
22             }
23         }
24         BigInteger f[] = new BigInteger[55];
25         BigInteger g[] = new BigInteger[55];
26         f[1] = BigInteger.ONE;
27         for (int i = 2; i <= 50; i++) {
28             g[i] = BigInteger.ZERO;
29             for (int j = 1; j < i; j++) {
30                 g[i] = g[i].add(C[i - 1][j - 1].multiply(f[j]).multiply(h[i - j]));
31             }
32             f[i] = h[i].subtract(g[i]);
33         }
34         int n;
35         Scanner cin = new Scanner(System.in);
36         while (cin.hasNext()) {
37             n = cin.nextInt();
38             if (n == 0)
39                 break;
40             System.out.println(f[n]);
41         }
42     }
43 
44     public static void main(String[] args) {
45         new Main();
46     }
47 }

 

posted @ 2017-02-11 23:12  小草的大树梦  阅读(333)  评论(0编辑  收藏  举报