Dollar Dayz

Farmer John 想知道,在一家商品价格为1至K (1 <= K <= 100)的店有多少方法能正好花完他的N(1 <= N <= 1000)元钱 。商品数量充足。

 

Input

N 、 K. 


Output

FJ花钱的方法数 


Sample Input
5 3
Sample Output

5


Hint
1*3+1*2 
1*3+2*1 
1*2+3*1 
2*2+1*1 

5*1

这道题要注意对大数的处理!!


当N为0时,K不论为多少,dp[0]=1;

在货币种类K相同的情况下,随着钱数总和N的增加,我们会发现有这样的状态方程:dp[N]=dp[N]+dp[N-K];

因为之前的dp[N]是在循环下累加的结果,我们在逐个增加K后,只需要将dp[N](K=K-1)之前的状态下再增加个N=K+……        (……总和=N-K)这样的排列序列(例如上述N=4,K=2;N=5,K=3),即增加总钱数为K,货币有1-K-1的总排列数即可。因此得到状态方程。

#include <cstdio>
#define INF 100000000000000000
using namespace std;
long long dp[1001][2]; //0是高位,1是低位
int K,N;
int main()
{
    scanf("%d %d",&N,&K);
    dp[0][1]=1;//总价0元的用任何类型的钱去组合结果都是什么都不买->一种情况
    for(int i=1;i<=K;i++)
    {
        for(int j=i;j<=N;j++)
        {
      
            dp[j][1] += dp[j-i][1];//低位十八位
            //处理进位
            dp[j][0] += dp[j-i][0] + dp[j][1] / INF;	//高位进位
            dp[j][1] %= INF;	//低位只取前十八位
        }
    }
    //两数合并成一个大数的输出
    if(dp[N][0]) printf("%lld",dp[N][0]);
    printf("%lld\n",dp[N][1]);
    return 0;
}
一维数组表示是现代码:

#include<iostream>  
#include<cstring>  
using namespace std;  
long long int inf=1000000000000000000;   //大数  
    //用j种价格配出金额i的方案数  
long long int a[1005];  //低位  
long long int b[1005];  //高位  
  //2^63~=9*10^18,所以用a数组表示前18位数,用b数组表示后18位数  
  
int main()  
{  
    int i,j,n,k;  
    cin>>n>>k;  
    memset(a,0,sizeof(a));  
    memset(b,0,sizeof(b));  
    a[0]=1;  //用任何种配0都是1 -> 什么都不用  
    for(j=1;j<=k;j++)  
    {  
        for(i=j;i<=n;i++)  
        {  
            //if(i<j)  另一种方法,i初始值为1时  
              //  continue;  
            b[i]=(b[i]+b[i-j])+(a[i]+a[i-j])/inf;  
            a[i]=(a[i]+a[i-j])%inf;  
        }  
    }  
    if(b[n])  
        cout<<b[n];  
    cout<<a[n]<<endl;  
    return 0;  
} 



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值