杭电Acm-母函数题目解题报告
今天是腊月29,今年没有30。所以,今晚就是除夕夜了。由于要找工作,练内功,所以,过年也不能够放松。今天做的题目是母函数相关的母函数就Generation Function,也叫生成函数,是组合数学中的一个概念。我请教了@微博Koth 他说了一个很典型,很简答的例子,可以很好的理解母函数的概念。例如求:
x+2y=10的非负整数解的个数------①
我们直观的看(x,y)的取值有:(0,5),(2,4),(4,3)等。那么从组合数学的角度来讲,我们要怎么思考呢x可能的取值0,1,2,3...y同样的取值也是如此。根据组合数学的思想,x的所有情况乘以y的所有情况,得到的就是真个解得所有的个数。将这个思想表示为如下的公式:
(1 + x + x^2 + x^3+...)(1 + x^2 + x^4 + x^6 +...)------②
第一个括号中,1表示x取0,x表示x取1,x^2表示x取2,依此类推。第二个括号中,x^2表示y取1(2 = 1 * 2),x^4表示y取2(4 = 2 * 2),依此类推。可得。通过观察,我们可以得到,②括号中指数,就表示①中的直,比如x^4中的4就是y取2的时候,即2*y的值。那么,我们展开②式,ax^b的意义就是 x + 2y = b 的非负整数解得个数为a。
杭电ACM的1028,1398,1171都是关于母函数的。而且都是相对比较基础的题目。只要能够将母函数的表示出来,找到系数和指数的含义,就能够顺利的解出题目。稍后简单分析一下几个题目。
- 1028题
import java.util.Scanner;
public class P1028 {
public static void main(String[] args) {
int[] c1 = new int[121];
int[] c2 = new int[121];
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n = in.nextInt();
for (int i = 0; i <= n; ++i) {
c1[i] = 1;
c2[i] = 0;
}
for (int i = 2; i <= n; ++i) {
for (int j = 0; j <= n; ++j)
for (int k = 0; k <= n; k += i)
c2[k + j] += c1[j];
for (int j = 0; j <= n; ++j) {
c1[j] = c2[j];
c2[j] = 0;
}
}
System.out.println(c1[n]);
}
}
}
- 1398题
import java.util.Scanner;
public class P1398 {
private static int[] coinType = new int[18];
static {
for (int i = 1; i < 18; ++i)
coinType[i] = i * i;
}
public static void main(String[] args) {
int[] c1 = new int[301];
int[] c2 = new int[301];
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n = in.nextInt();
if (0 == n) return;
for (int i = 0; i <= n; ++i) {
c1[i] = 1;
c2[i] = 0;
}
for (int i = 2; i < 18; ++i) {
for (int j = 0; j <= n; ++j)
for (int k = 0; k + j <= n; k += coinType[i])
c2[k + j] += c1[j];
for (int j = 0; j <= n; ++j) {
c1[j] = c2[j];
c2[j] = 0;
}
}
System.out.println(c1[n]);
}
}
}
- 1171题
import java.util.Arrays;
import java.util.Scanner;
public class P1171 {
public static void main(String[] args) {
int[] c1 = new int[250001];
int[] c2 = new int[250001];
Scanner in = new Scanner(System.in);
while (in.hasNextLine()) {
int n = Integer.parseInt(in.nextLine());
if (n < 0) return;
int[] v = new int[n + 1];
int[] m = new int[n + 1];
int sum = 0;
for (int i = 1; i <= n; ++i) {
String[] ss = in.nextLine().split("[ ]+");
v[i] = Integer.parseInt(ss[0]);
m[i] = Integer.parseInt(ss[1]);
sum += v[i] * m[i];
}
Arrays.fill(c1, 0);
Arrays.fill(c2, 0);
for (int i = 0; i <= v[1] * m[1]; i += v[1])
c1[i] = 1;
int len = v[1] * m[1];
for (int i = 2; i <= n; ++i) {
for (int j = 0; j <= len; ++j)
for (int k = 0; k <= v[i] * m[i]; k += v[i])
c2[k + j] += c1[j];
len += v[i] * m[i];
for (int j = 0; j <= len; ++j) {
c1[j] = c2[j];
c2[j] = 0;
}
}
for(int i= sum / 2; i >= 0; --i)
if(c1[i] != 0)
{
System.out.println((sum - i) + " " + i);
break;
}
}
}
}