在床上打代码也是够爽
题意:
屌屌的约翰去买东西,他一共打算买N元钱的东西,他有无穷张1-K面值的钱,问他又多少中方法不找零支付N元钱。
(1 <= N <= 1000, 1 <= K <= 100)
果断是动态规划或者记忆化搜索,但是N,K太大,爆long long,高精度加法即可
但是十进制高精度TLE,采用高位进制,最终采用10^5进制,最大一组数据也可以瞬出。高位进制输出时注意会少0,要判断。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<ctime>
using namespace std;
#define mxn 1010
#define mxk 110
int n,k;
struct bign{
int a[10];
int len;
bign(){len=-1;}
bign set(int in){
len=0;
while(in){
a[len++]=in%100000;
in/=100000;
}
return *this;
}
bign(int in){set(in);}
void set(){len=-1;}
bool ok(){return len!=-1;}
bign operator + (const bign& in)const{
bign ret;
int pre=0;
ret.len=max(in.len,len);
for(int i=0;i<ret.len;++i){
int tem=pre;
if(i<len) tem+=a[i];
if(i<in.len) tem+=in.a[i];
pre=tem/100000;
ret.a[i]=tem%100000;
}
if(pre) ret.a[ret.len++]=pre%100000;
return ret;
}
void print(){
printf("%d",a[len-1]);
for(int i=len-2;i>=0;--i){
if(a[i]/10000==0) printf("0");
else if(a[i]/1000==0) printf("00");
else if(a[i]/100==0) printf("000");
else if(a[i]/10==0) printf("0000");
printf("%d",a[i]);
}
}
};
bign dp[mxn][mxk];
bign dfs(int now,int val){
if(dp[now][val].ok()) return dp[now][val];
//cout<<"now "<<now<<" val "<<val<<endl;
if(now==n) return dp[now][val].set(1);
dp[now][val].set(0);
if(val==k+1) return dp[now][val].set(0);
for(int i=0;i*val+now<=n;++i)
dp[now][val]=dp[now][val]+dfs(now+i*val,val+1);
return dp[now][val];
}
int main(){
scanf("%d%d",&n,&k);
bign ans=dfs(0,1);
ans.print();
puts("");
return 0;
}