地址
http://acm.hdu.edu.cn/showproblem.php?pid=2110
定位
排列组合问题
母函数
大数陷阱
分析
物品种类数 n ,第
i 行输入:物品价值 v[i] ,物品数量 n2[i] 。目标总价值 ∑niv[i]n2[i]3 ,可能不被3整除,及目标总价值不是整数。又因为 v[i] 和 n2[i] 均为整数,一定没有分配方案,直接输出 sorry。
母函数
g(x)=(1+xv[1]+...+xn2[1]v[1])...(1+xv[i]+...+xn2[i]v[i])...(1+xv[n]+...+xn2[n]]v[n])
代码
- #include <iostream>
- #include <stdio.h>
- #include <string.h>
- using namespace std;
- int a[10001],b[10001];
- int v[101],n1[101],n2[101];
- /*************************************************
- Function: GenerateFunc(int N,int P)
- Description: 生成函数系数计算
- Input: int N : 相乘的因子个数
- int P : 待求的最大指数
- Output: void
- Return: void
- Others: 修改的全局变量 a[] b[]
- 只读的全局变量 v[] n1[] n2[]
- *************************************************/
- void GenerateFunc(int N,int P) {
- memset(a,0,sizeof(a));
- a[0]=1;
- for(int i=0; i<N; i++) {
- memset(b,0,sizeof(b));
- for(int j=n1[i]; j<=n2[i]&&j*v[i]<=P; j++) {
- for(int k=0; k+j*v[i]<=P; k++) {
- b[k+j*v[i]]+=a[k];
- b[k+j*v[i]]%=10000;
- }
- }
- memcpy(a,b,sizeof(b));
- }
- }
- int main() {
- int n,p;
- memset(n1,0,sizeof(n1));
- scanf(”%d”,&n);
- while(n!=0) {
- p=0;
- for(int i=0; i<n; i++) {
- scanf(”%d %d”,&v[i],&n2[i]);
- p+=v[i]*n2[i];
- }
- if(p%3!=0) {
- printf(”sorry\n”);
- scanf(”%d”,&n);
- continue;
- }
- p/=3;
- GenerateFunc(n,p);
- if(a[p]==0) {
- printf(”sorry\n”);
- } else {
- printf(”%d\n”,a[p]);
- }
- scanf(”%d”,&n);
- }
- }
性能
Exe.Time | Exe.Memory | Code Length | Language |
---|---|---|---|
15MS | 1872K | 1168B | c++ |
总结
- 大数限制
输出结果要求对10000取模,暗示方案数会很大,而且中间计算过程很可能出现大数。因此,不仅要在最后输出时做取模运算,在中间计算过程中,也要及时取模规避大数问题。