题意 给你n和m,问你用1...m这些数,每种无限个,相互组合,形成求和为n的方案数。
思路 dp(i,j) 表示组成求和为i,且选用的这些数最小的要>j方案数。
转移:dp(i,j) = dp(i,j+1) + dp(i-j,j)
注意最后数会超long long 用高精度数。
C++:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
const int maxn = 1003;
const int maxm = 102;
int n,m;
const int MAXSIZE = 100;
struct BigInt{
public:
int a[MAXSIZE];
int length;
public:
BigInt():length(0){memset(a,0,sizeof(a));}
BigInt(string s);
BigInt(int b);
BigInt(const BigInt& c);
BigInt operator=(int b);
BigInt operator=(string s);
};
BigInt::BigInt(string s)
{
memset(a,0,sizeof(a));
*this = s;
}
BigInt::BigInt(int b)
{
memset(a,0,sizeof(a));
*this = b;
}
BigInt::BigInt(const BigInt& c)
{
int i;
memset(a,0,sizeof(a));
length = c.length;
memset(a,0,sizeof(a));
for(i=0;i<length;i++)
{
a[i] = c.a[i];
}
}
BigInt BigInt::operator=(int b)
{
memset(a,0,sizeof(a));
if(b==0)
{
a[0] = 0;
length = 1;
}
if(b<0)
{
b = -b;
}
for(length=0;b>0;length++)
{
a[length] = b%10;
b /= 10;
}
return *this;
}
BigInt BigInt::operator=(string s)
{
int i;
length = s.length();
memset(a,0,sizeof(a));
for(i=0;i<length;i++)
{
a[length-i-1] = (int)(s[i] - '0');
}
return *this;
}
BigInt operator+(const BigInt& d,const BigInt& b)
{
int i;
int jinWei = 0;
BigInt sum;
int max_length = (d.length<b.length)?b.length:d.length;
for(i=0;i<max_length;i++)
{
jinWei = d.a[i]+b.a[i]+jinWei;
sum.a[i] = jinWei%10;
jinWei/=10;
}
sum.length = i; //sum.length 易忘赋值
if(jinWei!=0)
{
sum.a[i] = jinWei; //加上最高位进位
sum.length++;
}
return sum;
}
BigInt operator-(const BigInt& d,const BigInt& b) //适宜d>b时
{
int i,j;
int tuiWei = 0;
BigInt sum;
int max_length = (d.length<b.length)?b.length:d.length;
for(i=0;i<max_length;i++)
{
tuiWei = d.a[i]-b.a[i]-tuiWei;
if(tuiWei>=0)
{
sum.a[i] = tuiWei;
tuiWei = 0;
}
else
{
sum.a[i] = 10+tuiWei;
tuiWei = 1;
}
}
sum.length = i; //sum.length 易忘赋值
for(j=i-1;sum.a[j]==0&&j>0;j--)
sum.length--;
return sum;
}
BigInt operator*(const BigInt& d,const BigInt& b)
{
int i,j,k;
int jinWei=0;
BigInt temp = 0;
BigInt fuck = 0;
if(b.a[0]==0&&b.length == 1||d.a[0]==0&&d.length == 1)
{
return b;
}
for(i=0;i<b.length;i++) //b作为乘数
{
jinWei = 0;
temp = 0;
for(j=0;j<d.length;j++) //a*b[i]
{
jinWei = d.a[j]*b.a[i] + jinWei;
temp.a[j] = jinWei%10;
jinWei /= 10;
}
temp.length = j;
if(jinWei!=0)
{
temp.a[j] = jinWei;
temp.length++;
}
if(i!=0)
{
for(k=temp.length-1;k>=0;k--) //左移i位
{
temp.a[k+i] = temp.a[k];
temp.a[k] = 0;
}
temp.length += i;
}
fuck = fuck+temp;
}
return fuck;
}
bool operator<(const BigInt& d,const BigInt& b)
{
if(d.length<b.length)
return true;
if(d.length>b.length)
return false;
for(int i=b.length-1;i>=0;i--)
{
if(d.a[i]>b.a[i])
return false;
if(d.a[i]<b.a[i])
return true;
}
return false;
}
bool operator==(const BigInt& d,const BigInt& b)
{
if(d.length!=b.length)
return false;
for(int i=b.length-1;i>=0;i--)
{
if(d.a[i]!=b.a[i])
return true;
}
return true;
}
bool operator!=(const BigInt& d,const BigInt& b)
{
return !(d==b);
}
bool operator>(const BigInt& d,const BigInt& b)
{
return !(d==b||d<b);
}
bool operator<=(const BigInt& d,const BigInt& b)
{
return !(d>b);
}
bool operator>=(const BigInt& d,const BigInt& b)
{
return !(d<b);
}
/
/
char* toString(BigInt a)
{
int i;
static char s[MAXSIZE];
for(i=a.length-1;i>=0;i--)
{
s[a.length-i-1] = (char)(a.a[i]+'0');
}
s[a.length] = '\0';
return s;
}
BigInt dp[maxn][maxm];
int main()
{
int i,j;
while(scanf("%d%d",&n,&m) == 2)
{
for(i=1;i<=m;i++)
{
dp[0][i] = 1;
}
for(i=1;i<=n;i++)
{
for(j=min(m,i);j>=1;j--)
{
dp[i][j] = dp[i][j+1] + dp[i-j][j];
}
}
char* tmp = toString(dp[n][1]);
printf("%s\n",tmp);
}
return 0;
}
Java
import java.util.*;
import java.math.*;
public class Main{
static final int maxn = 1003;
static final int maxm = 102;
static BigInteger[][] dp = new BigInteger[maxn][maxm];
static Scanner cin = new Scanner(System.in);
static public void main(String args[]){
int n,m;
while(cin.hasNextInt() == true)
{
n = cin.nextInt();
m = cin.nextInt();
int i = 0,j = 0;
for(i = 1;i<=m;i++)
dp[0][i] = BigInteger.ONE;
for(i=1;i<=n;i++)
{
for(j=Math.min(i,m);j>=1;j--)
{
if(dp[i][j+1] == null)
dp[i][j+1] = BigInteger.ZERO;
if(dp[i-j][j] == null)
dp[i-j][j] = BigInteger.ZERO;
dp[i][j] = BigInteger.ZERO;
dp[i][j] = dp[i][j+1].add(dp[i-j][j]);
}
}
System.out.println(dp[n][1].toString());
}
}
}