4 1 2 3 4
1 1 2 1 3 2 4 2 5 2 6 2 7 2 8 1 9 1 10 1
无
Hungar
思路 :很明显是母函数
#include<stdio.h> #include<string.h> int num[111],val[111]; int c1[10000+100],c2[10000+100]; #define mod 100000007; int main() { int n,i,j,k,sum; while(scanf("%d",&n)!=EOF) { sum=0; memset(num,0,sizeof(num)); for(i=1;i<=n;i++) { scanf("%d",&val[i]); num[val[i]]=1; sum+=val[i]; } memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); for(j=0;j<=val[1]*num[val[1]];j+=val[1])//限制了每种的个数 最多为 num[val[i]]*val[i] 由于本题都是1 可以去掉不写 /*如 质量为1 的砝码有4个 则母函数第一个式子为为 1+x^1+x^2+x^3+x^4*/ c1[j]=1; for(i=2;i<=n;i++) { for(j=0;j<=sum;j++)//指向上一次已经计算过的式子的项 for(k=0;k+j<=sum&&k<=num[val[i]]*val[i];k+=val[i])//限制了每种的个数就要这样写了 {//k指向当前要成的式子的项 c2[k+j]+=c1[j]%mod; c2[k+j]%=mod; } for(k=0;k<=sum;k++) { c1[k]=c2[k]%mod; c2[k]=0; } } for(i=1;i<=sum;i++) if(c1[i]) printf("%d %d\n",i,c1[i]); } return 0; }
下面的是官方的解题报告 :
A.Weight
由题可知,砝码数量不超过100,每个砝码的重量不超过100,那么总重不会超过10000.
我们可以申请一个数组a,a[i]表示组成重量i的数量。
那么对于每个砝码,我们都对a数组遍历一遍,
当a[i]是真值时,那么a[i+当前砝码的重量]+=a[i](不要忘了求余),
所以要从尾部开始遍历,不能从头部开始遍历。
但是我们可以剪枝一下,每次都是从10000开始遍历到0有点漫长。
所以我们可以定义一个数all = 0;
all存的是当前砝码以及该砝码之前的所有砝码的总和重量,所以每次只要从all开始遍历到0即可。
#include <cmath> #include <cstdio> #include <iostream> using namespace std; #define mod 100000007 #define N 110 #define M 10005 int a[M]; int main() { int n; while (~scanf("%d", &n)) { int all = 0; memset(a, 0, sizeof(a)); a[0] = 1; for (int i = 0; i < n; i++) { int x; scanf("%d", &x); all += x; for (int j = all; j >= 0; j--) { if (a[j]) a[j + x] = (a[j + x] + a[j]) % mod; } } for (int i = 1; i <= all; i++) { if (a[i]) printf("%d %d\n", i, a[i]); } } return 0; }