题解:
这道题是一道完全背包,递推式为:dp[i][j] = dp[i][j-1]+dp[i-j][j];
表示用前j个数组成i包括两种情况:不包括j组成i和用j组成i-j。
但是因为结果很大,而是用大数又会超时,看到网上的解法,但是博主也是在大数跑出来范围后才决定用这种方法,所以还是比较坑的。
因为LL最大为10^18数量级,所以用10^18取余。
代码实现:
<span style="font-size:18px;">#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define LL long long
using namespace std;
int N,K;
LL INF;
LL dp[1010][110];
LL mod[1010][110];
int main()
{
INF = 1;
for( int i = 0; i < 18; i++ )
INF *= 10;
scanf("%d%d",&N,&K);
memset(dp,0,sizeof(dp));
memset(mod,0,sizeof(mod));
for( int i = 0; i <= K; i++ )
dp[0][i] = 1;
for( int i = 1; i <= K; i++ ){
for( int j = 1; j <= N; j++ ){
if( j < i ){
dp[j][i] = dp[j][i-1];
mod[j][i] = mod[j][i-1];
}
else{
dp[j][i] = dp[j][i-1]+dp[j-i][i];
mod[j][i] = mod[j][i-1]+mod[j-i][i]+dp[j][i]/INF;
dp[j][i] %= INF;
}
}
}
if( mod[N][K] == 0 ){
printf("%I64d\n",dp[N][K]);
}
else{
printf("%I64d%I64d\n",mod[N][K],dp[N][K]);
}
return 0;
}
</span>