HDU 2566 统计硬币 (母函数或dfs)

统计硬币

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8202    Accepted Submission(s): 5606


Problem Description
假设一堆由1分、2分、5分组成的n个硬币总面值为m分,求一共有多少种可能的组合方式(某种面值的硬币可以数量可以为0)。
 
Input
输入数据第一行有一个正整数T,表示有T组测试数据;
接下来的T行,每行有两个数n,m,n和m的含义同上。
 
Output
对于每组测试数据,请输出可能的组合方式数;
每组输出占一行。
 
Sample Input
2 3 5 4 8
 
Sample Output
1 2
 
Author
lemon
 
Source
 
Recommend
yifenfei   |   We have carefully selected several similar problems for you:  2561 2562 2152 2564 2082 
 
分析:可以用二维的母函数来记录一下数量,也可以用DFS
 
母函数:
#include<iostream>
#include <cstring>
using namespace std;
#define M 1000   //M为(x的最大指数+1)
#define MAXN 130      //MAXN为最大有多少项相乘
int a[M][150],b[M][150];//a[M]中存最终项系数;b[M]中存取中间变量;
int main()
{
    int m,n;
    int i,j,k,r;
    m=MAXN;
    int t;
    scanf("%d",&t);
    while(t--){
       scanf("%d%d",&r,&n);
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        //n为所求的指数的值: ";
        //因为只求指数为n的系数的值:所以循环只到n就结束
        for(i=0;i<=n;i++)//初始化第一个式子:(1+X+X^2+X^3+...) 所以将其系数分别存到a[n]
        {
            a[i][i]=1;
        }
        for(i=2;i<=5;i=i+3)//从第2项式子一直到第n项式子与原来累乘项的和继续相乘
        {
            for(j=0;j<=n;j++)//从所累乘得到的式子中指数为0遍历到指数为n 分别与第i个多项式的每一项相乘
                 for(k=0;k+j<=n&&k/i<=r;k+=i)//第i个多项式的指数从0开始,后面的每项指数依次比前面的多i,比如当i=3时,第3项的表达式为(1+x^3+x^6+x^9+……),直到所得指数的值i+j>=n退出
                 {
                     for(int z=0;z+k/i<=r;z++){
                     b[j+k][z+k/i]+=a[j][z];
                     }//比如前面指数为1,系数为3,即a[1]=3 的一项和下一个表达式的指数为k=3的相乘,则得到的式子的系数为,b[j+k]=b[4]+=a[1],又a[1]=3,所以指数为4的系数为b[4]=3;
                 }
             for(j=0;j<=n;j++)//  然后将中间变量b数组中的值依次赋给数组a,然后将数组b清零,继续接收乘以下一个表达式所得的值
              {
                 for(int k=0;k<=r;k++){
                  a[j][k]=b[j][k];
                  b[j][k]=0;
                 }
              }
        }
        printf("%d
",a[n][r]);  // 指数为n的项的系数为:
    }
    return 0;
}

DFS:

#include <iostream>
#include  <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,ans;
void dfs(int x,int sum,int step)
{
    if(sum>m)return;
    if(sum==m&&step==n)
    {
    ans++;
    return;
    }
    if(step==n)
    return;
   if(x==5)
   {

    dfs(5,sum+5,step+1);
   }
   else if(x==1)
   {
     dfs(1,sum+1,step+1);
    dfs(2,sum+2,step+1);
    dfs(5,sum+5,step+1);
   }
   else if(x==2)
   {
   dfs(2,sum+2,step+1);
    dfs(5,sum+5,step+1);
   }
}
int main()
{
    int t;
   scanf("%d",&t);
   while(t--)
   {
       ans=0;
       scanf("%d%d",&n,&m);
       dfs(1,1,1);
       dfs(2,2,1);
       dfs(5,5,1);
       printf("%d
",ans);
   }
return 0;
}
 
原文地址:https://www.cnblogs.com/a249189046/p/7550752.html