标签:
所谓的母函数我觉得就是将一些组合数问题转化成多个多项式相乘,然后对系数做一些处理....
关于母函数的题有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; } } } }
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]); } }
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(""); } } }
标签:
原文地址:http://www.cnblogs.com/icodefive/p/4578530.html