zoukankan      html  css  js  c++  java
  • ACM母函数详解 整数划分详解 java

    引言

             关于什么是母函数,以及母函数的用途,为什么整数划分可以使用母函数解决,请看

             http://hi.baidu.com/syxcs123/blog/item/6f8090455f36058cb2b7dc14.html

    分析

    * 计算整数n的所有划分方法

    * 通过母函数模板来计算整数划分,

    * 多项式:(1+x+x^2+x^3+x^4+x^5+....)*(1+x^2+x^4+x^6+x^8+x^10+....)*(1+x^3+x^6+x^9+x^12....).....(#式)

    * 本函数就是展开#式多项式,得到最后多项式的系数。

    * c1、c2存储多项式的系数,比如多项式1+x+x^2+x^3+x^4+x^5+....,c1[0]=1,c1[1]=1,...,表示x的多少吃饭的系数为多少,如c2[3]=5,表示5x^3。

    * c1保存最终的系数,c2保存当前相乘的2个多项式系数,如下:

    * 第一个多项式(1+x+x^2+...)[i=1],我们直接保存在c1中,即c1[0...n]=1,

    * 在上面保存的多项式(1+x+x^2+...)(1),与下一个括号(1+x^2+x^4+...)[i=2](2)相乘,模拟手工计算:

    * 一、(1)中的1[j=0]和(2)中的每项[k=0...n]相乘,得到1+x^2+x^4+...,在把x^0(1)和(1+x+x^2+...)合并同类项c1[0],即幂数相同的系数相加,

    * 如x^2和(1+x+x^2+...)中的x^2系数相加,而(1+x+x^2+...)所有系数保存在c2数组中, 所以和c1[2]的值相加,

    * x^4在和(1+x+x^2+...)的c1[4]值相加,这样一直下去一直到整数n,因为整数拆分方案数就是最后x^n的系数。

    * 二、(1)中的x[j=1]和(2)中的每项[k=0...n]相乘,得到x+x^3+x^5+...,在按照上面方法和c1合并相同幂的项,放到c2,比如x[j=1]和k[k=0]相乘,

    * 即x^1 * x^0 , 得到的系数j+k,x^k[k=0]是(2)式得到的,系数为1,但x[j=1]的系数是c1[j],所以 x^(j+k)的系数是c2中原来的系数+c1[j]的值,因x^k系数为1,忽略。

    * 三、这样循环下去,即可把(1+x+x^2+...)(1),(1+x^2+x^4+...)[i=2](2)展开,且各指数的系数放在c2中。在把c2中的系数放到c1中,计算与第三个式子展开(1+x^3+x^6+...)。

    * 依次类推,一直到n

    算法与代码

    /**
    * 整数划分模板
    * @author syx
    * Date 2011年7月7日 14:30:14
    */
    public class GeneratingFunction {
        public static void main(String[] args) {
            System.out.println(doWork(6));
        }
        
        /**
         * 计算整数n的所有划分方法
         * 通过母函数模板来计算整数划分,
         * 多项式:(1+x+x^2+x^3+x^4+x^5+....)*(1+x^2+x^4+x^6+x^8+x^10+....)*(1+x^3+x^6+x^9+x^12....).....(#式)
         * 本函数就是展开#式多项式,得到最后多项式的系数。
         * c1、c2存储多项式的系数,比如多项式1+x+x^2+x^3+x^4+x^5+....,c1[0]=1,c1[1]=1,...,表示x的多少吃饭的系数为多少,如c2[3]=5,表示5x^3。
         * c1保存最终的系数,c2保存当前相乘的2个多项式系数,如下:
         * 第一个多项式(1+x+x^2+...)[i=1],我们直接保存在c1中,即c1[0...n]=1,
         * 在上面保存的多项式(1+x+x^2+...)(1),与下一个括号(1+x^2+x^4+...)[i=2](2)相乘,模拟手工计算:
         * 一、(1)中的1[j=0]和(2)中的每项[k=0...n]相乘,得到1+x^2+x^4+...,在把x^0(1)和(1+x+x^2+...)合并同类项c1[0],即幂数相同的系数相加,
         * 如x^2和(1+x+x^2+...)中的x^2系数相加,而(1+x+x^2+...)所有系数保存在c2数组中, 所以和c1[2]的值相加,
         * x^4在和(1+x+x^2+...)的c1[4]值相加,这样一直下去一直到整数n,因为整数拆分方案数就是最后x^n的系数。
         * 二、(1)中的x[j=1]和(2)中的每项[k=0...n]相乘,得到x+x^3+x^5+...,在按照上面方法和c1合并相同幂的项,放到c2,比如x[j=1]和k[k=0]相乘,
         * 即x^1 * x^0 , 得到的系数j+k,x^k[k=0]是(2)式得到的,系数为1,但x[j=1]的系数是c1[j],所以 x^(j+k)的系数是c2中原来的系数+c1[j]的值,因x^k系数为1,忽略。
         * 三、这样循环下去,即可把(1+x+x^2+...)(1),(1+x^2+x^4+...)[i=2](2)展开,且各指数的系数放在c2中。在把c2中的系数放到c1中,计算与第三个式子展开(1+x^3+x^6+...),
         * 依次类推,一直到n
         * @param n 待划分的数
         * @return 划分方案数
         */
        public static int doWork(int n) {
            int[] c1 = new int[n+1];
            int[] c2 = new int[n+1];
            for(int i=0; i<=n; i+=1) {
                c1[i] = 1;
                c2[i] = 0;
            }
            for(int i=2; i<=n; i+=1) {
                for(int j=0; j<=n; j+=1) {
                    for(int k=0; k+j<=n; k+=i) {
                        c2[j+k] += c1[j];
                    }
                }
                for(int j=0; j<=n; j+=1) {
                    c1[j] = c2[j];
                    c2[j] = 0;
                }
            }
            return c1[n];
        }
    }
  • 相关阅读:
    挺好的 "简历修改"
    请问谁会破解QQ空间相册的密码呀教我下谢谢!!。
    SEO工具,站长必备
    解决vs2005自带水晶报表次数的限制的次数
    虚拟主机如何实现泛域名解析?
    读出数据库里面的数据,来 绑定列表框 DropDownList1
    取出数据里面相同的记录
    如何让文本框输入字母自动换行???? 很有意思的哦 
    net事件丢失解决方法
    暑假集训每日一题0727 (网络流)
  • 原文地址:https://www.cnblogs.com/syxchina/p/2197205.html
Copyright © 2011-2022 走看看