zoukankan      html  css  js  c++  java
  • hdu1028

    博客图片

    题目链接

    hdu1028

    题目概述

            求一个整数(N)的可重无序拆分.

    解题思路

            稍加变换,原问题等价于方程:

    [1e_1+2e_2+3e_3+cdots +ne_n=n,\,(e_i ge 0, i= 1, 2, 3,dots) ]

    解的个数,可以看做是将(n)个相同的小球放到(n)个相同的盒子允许空盒的数目.对应的结果就是函数:

    [g(x) = (1+x+x^2+x^3+cdots)(1+x^2+x^4+cdots)cdots(1+x^n+x^{2n}+cdots) ]

    展开式中(x^n)项的系数.对于(1,x^i,x^{2i},dots)可以理解为使用整数(i,0,1,2,dots)次,得到整数(1,i,2i,dots.)所以展开式中的(x^n)就是(x^{1e_1},x^{2e_2},dots)相乘,使得(x)的指数部分之和是(n.)

    注意

            因为这里每一个整数(i)使用的数量都没有限制,所以写的是(1,x^i,x^{2i},dots),假设整数(i)使用的次数只能是奇数,那么整数(i)的展开应该是((x^i+x^{3i}+dots));或者整数(i)的使用次数只能是序列({b_1,b_2,dots})中的,那么(i)的展开应该是((x^{ib_1}+x^{ib_2}+dots).)

            另外注意上面方程前面那个(e_i)前面的的系数(i),(e_i)表示的是使用这个系数多少次,而这个系数表示另外一种约束,可以这样理解,就是使用一个东西必须要使用(i)次,如果上面的方程变为:

    [e_1+e_2+e_3+cdots +e_n=n,\,(e_i ge 0, i= 1, 2, 3,dots) ]

    那么对应的母函数就是:

    [g(x) = (1+x+x^2+x^3+cdots)(1+x^1+x^2+cdots)cdots(1+x^2+x^{2}+cdots) = (1+x+x^2+x^3+cdots)^n. ]

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 200;
    ll buf[N];
    ll temp[N];
    
    
    void calculate(){
        fill(buf, buf + N, 1);
        fill(temp, temp + N, 0);
        for (int k = 2; k < N; ++k){
            for (int i = 0; i < N; ++i){
                for(int j = 0; i+j < N; j +=k ){
                    // temp是当前的k的展开式与上一轮计算的结果.
                    temp[i + j] += buf[i];
                }
            }
            // 更新这一轮的结果.
            memcpy(buf, temp, sizeof(ll)*N);
            fill(temp, temp + N, 0);
        }
    }
    
    int main(int argc, const char** argv) {
        calculate();
        int n;
        while (~scanf("%d",&n)){
            printf("%lld
    ", buf[n]);
        }
        return 0;
    }
    

    下面通过这个表格给出计算((1+x^1+x^2+x^3+x^4)(1+x^2+x^4))的计算过程:
    (表格A(上一轮计算的结果))

    0 1 2 3 4 5 6 7 8 9
    1 1 1 1 1 1 1 1 1 1

    (表格B(这一轮计算的结果))

    0 1 2 3 4 5 6 7 8 9
    1 1 1 1 1
    1 1 1 1 1
    1 1 1 1
    1 1 1 1
    1 1 1
    1 1 1
    1 1
    1 1
    1
    1

    (整理之后是这一轮计算的值(对应程序中的temp))

    0 1 2 3 4 5 6 7 8 9
    1 1 2 2 3 3 4 4 5 5

    (更新这一轮计算的结果准备计算下一轮(对应程序中的buf))

    0 1 2 3 4 5 6 7 8 9
    1 1 2 2 3 3 4 4 5 5

    按照上面表格所示的那样,先计算相邻的两项系数作为当前一轮的计算结果,然后在下一轮中座椅一项与下一项进行计算得到下一轮就散的记过,然后更新,这样滚动更新计算,最后的buf中的系数就是整数拆分的结果(这里为了便于识别,没有将表格中空白的0显示的标出).

    其它

  • 相关阅读:
    微软消息队列
    使用Memcached Provider客户端的increment()||decrement()操作小结
    SQL While And Sql Array
    好管理是成功的99%
    Javascript图片无缝滚动
    javascript数组复习
    前端面试题--js切换td中的值
    推荐使用:易企在线客服升级版
    drupal中根据不同的内容类型节点显示不同的样式
    defer和async(原生js学习)转
  • 原文地址:https://www.cnblogs.com/2018slgys/p/13304900.html
Copyright © 2011-2022 走看看