硬币表示

有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。

给定一个int n,请返回n分有几种表示法。保证n小于等于100000,为了防止溢出,请将答案Mod 1000000007

测试样例:

6

返回:2

暴力方法:

void helper(int n,int res,int& count,int a[])
{
    if(n==3)
    {
        if(res%a[n])
            return;
        count=(count+1)%1000000007;
        return;
    }
    int k=res/a[n];
    for(int i=0;i<=k;i++)
        helper(n+1,res-i*a[n],count,a);
}
class Coins 
{
public:
    int countWays(int n) 
    {
        // write code here
        int a[4]={1,5,10,25};
        int count=0;
        helper(0,n,count,a);
        return count;
        
    }
};

动态规划1:

//设n=x1*1+x2*5+x3*10+x4*25 x1,x2,x3,x4>=0且为整数
//当x1,x2,x3,x4取不同的值时对应不同的表示方法
//对于x4而言它的取值范围为[0,n/25],它的每一种取值,表现出了
//一类表示方法,假设用dp[i][j]表示用i种硬币表示j分的硬币,当先确定
//最后一个硬币取得数量时,假设取k个,则上述状态的一个子状态为dp[i-1][j-k*b[i]]
//b[i]为第i种硬币的币值,k的不同取值对应了不同的子状态,将这些子状态加在一起就为最终状态


class Coins 
{
public:
    int countWays(int n) 
    {
        // write code here
        int a[4]={1,5,10,25};
        vector<vector<int> >dp(5,vector<int>(n+1,0));
        
        for(int j=0;j<=n;j++)
        {
            if(j==0)
                dp[0][j]=1;
            else
            {
                dp[0][j]=0;
            }
                
        }
        for(int j=1;j<=4;j++)
        {
            dp[j][0]=1;
        }
        
        for(int i=1;i<=4;i++)
        {
            for(int j=1;j<=n;j++)
            {
                for(int k=0;k<=j/a[i-1];k++)
                {
                    dp[i][j]=dp[i][j]%1000000007+dp[i-1][j-k*a[i-1]]%1000000007;
                }
            }
        }
        
        return dp[4][n];
        
    }
};
此时复杂度很高
动态规划2:

class Coins
{
public:
    int countWays(int n)
    {
        // write code here
        int a[4] = { 1, 5, 10, 25 };
        vector<vector<int> >dp(5, vector<int>(n + 1, 0));
 
        for (int j = 0; j <= n; j++)
        {
            if (j == 0)
                dp[0][j] = 1;
            else
            {
                dp[0][j] = 0;
            }
 
        }
        for (int j = 1; j <= 4; j++)
        {
            dp[j][0] = 1;
        }
 
        for (int i = 1; i <= 4; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (j >= a[i - 1])
                    dp[i][j] = (dp[i - 1][j] % 1000000007 + dp[i][j - a[i - 1]] % 1000000007) % 1000000007;
                else
                    dp[i][j] = dp[i - 1][j];
            }
        }
 
        return dp[4][n];
 
    }
};

也可以
class Coins {
public:
    int countWays(int n) {
        // write code here
        int coins[4]={1,5,10,25};
        int dp[100001] = {0};       
        dp[0] = 1;
        for(int i = 0;i < 4;++i){
            for(int j = coins[i];j <= n;++j){
                dp[j] =(dp[j]+dp[j-coins[i]])%1000000007;               
            }
        }
        return dp[n];
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值