码迷,mamicode.com
首页 > 其他好文 > 详细

母函数小结

时间:2015-06-15 18:11:36      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

所谓的母函数我觉得就是将一些组合数问题转化成多个多项式相乘,然后对系数做一些处理....

关于母函数的题有HDU 1171,1398,1709,2065,2069,2082,2152;POJ 3046,3716,3734

1.hdu 1171

题目大意给出一个n,接下来n行每行有v, m两个数表示有m个值为n的数,将这两个数分成两堆让两堆的差值的绝对值最小,其实用背包就可以轻易的解决这个问题,我们用母函数的思想来做一下。

首先对每一组v,m 我们可以构造出形如这样的公式(x^v+x^2v+x^3v....x^mv)。这个公式的含义就是在m个v中选出一种,然后将所有公式相乘,枚举x幂数最接近sum/2的那一项。

技术分享
    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int maxa = 260000;
    int v[100], m[100];
    bool a[2][maxa];
    int main(){
        int n;
        while(scanf("%d", &n)&&n >=0){
            int sum = 0;
            for(int i = 0;i < n; i++){
                scanf("%d%d", &v[i], &m[i]);
                sum += v[i] * m[i];
            }
            memset(a, 0, sizeof(a));
            a[0][0] = 1;
            for(int i =0 ;i < n; i++){
                for(int k = sum/2; k >= 0; k--){
                    if(a[i%2][k]){
                        for(int j = 0; j <= m[i]; j++){
                            if(k+j*v[i] > sum/2)break;
                            a[(i+1)%2][k+j*v[i]] = 1;
                        }
                    }
                }
            }
            for(int i = sum/2; i >= 0; i--){
                if(a[n%2][i]){
                    printf("%d %d\n", sum-i, i);
                    break;
                }
            }
        }
    }
View Code

2.hdu 1398

题目大意就是用一些x^2的数相加能得到n,有多少种情况,思路同上。

技术分享
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxa = 305;
int a[maxa];
int main(){
    int n;
    while(scanf("%d", &n), n){
        for(int i = 0; i <= n; i++){
            a[i] = 1;
        }
        for(int i = 2; i*i <= n; i++){
            for(int k = n; k >= 0; k--){
                for(int j = 1; k + j*i*i <= n; j++){
                    a[k+j*i*i]  += a[k];
                }
            }
        }
        printf("%d\n", a[n]);
    }
}
View Code

3.hud1709

给出一些和一个天平砝码,问这些砝码在[1,sum]之间不能称出的重量。

做到这的时候就感觉母函数难道就是背包吗...希望下面的题能给我惊喜....

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxa = 20005;
bool w[maxa];
int a[105];
int main(){
    int n;
    while(scanf("%d", &n) !=EOF){
        int sum = 0;
        for(int i =0 ;i < n; i++){
            scanf("%d", &a[i]);
            sum += a[i];
        }
        memset(w, 0, sizeof(w));
        w[10000] = 1;
        int zero = 10000;
        for(int i = 0; i< n; i++){
            for(int k = zero + sum; k >= zero - sum; k --){
                if(w[k]){
                    if(k+a[i] <= sum+zero)
                        w[k+a[i]] = 1;
                }
            }
            for(int k = zero - sum; k <= zero +sum ; k++){
                if(w[k]){
                    if(k - a[i] >= zero -sum)
                        w[k-a[i]] = 1;
                }
            }
        }
        int ans = 0;
        for(int i =zero+1; i <= zero+sum; i++){
            if(w[i] == 0) ans ++;
        }
        if(!ans)printf("0\n");
        else{
            printf("%d\n", ans);
            for(int i =zero+1 ;i <= zero+sum; i++){
                if(!w[i]){
                    ans --;
                    printf("%d", i-zero);
                    if(ans !=0)printf(" ");
                }
            }
            puts("");
        }
    }
}
View Code

 

母函数小结

标签:

原文地址:http://www.cnblogs.com/icodefive/p/4578530.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!