题意
- 有1~k,这k个数,每种数可以用任意多次,问你组成n的方案数
- N<=1000,k<=100
思路
- 就是完全背包,把k种物品,第i种重量为i,重量限制为N的方案数,只要把原本的max改为sum即可
- 由于k,n比较小,我就没优化的写了一个,将将过。。之后重写了一个优化后的,就都贴出来了
- 注意要用高精度数
实现
没优化的
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXSIZE = 50;
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;
return *this;
}
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;
if(jinWei!=0)
{
sum.a[i] = jinWei;
sum.length++;
}
return sum;
}
BigInt operator-(const BigInt& d,const BigInt& 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;
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++)
{
jinWei = 0;
temp = 0;
for(j=0;j<d.length;j++)
{
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--)
{
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;
}
int n,k;
BigInt dp[2][1005];
int main(){
cin>>n>>k;
dp[0][0] = BigInt(1);
for (int i=1;i<=k;i++){
for (int j=0;j<=n;j++){
dp[i&1][j] = BigInt(0);
for (int k=0;k*i <= j;k++){
dp[i&1][j] = dp[i&1][j] + dp[(i-1)&1][j-k*i];
}
}
}
cout <<toString(dp[k&1][n] )<<'\n';
return 0;
}
优化后的
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXSIZE = 50;
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;
return *this;
}
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;
if(jinWei!=0)
{
sum.a[i] = jinWei;
sum.length++;
}
return sum;
}
BigInt operator-(const BigInt& d,const BigInt& 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;
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++)
{
jinWei = 0;
temp = 0;
for(j=0;j<d.length;j++)
{
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--)
{
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;
}
int n,k;
BigInt dp[1005];
int main(){
cin>>n>>k;
dp[0] = BigInt(1);
for (int i=1;i<=k;i++){
for (int j=0;j<=n;j++){
if (j >= i)
dp[j] = dp[j-i] + dp[j];
}
}
cout <<toString(dp[n] )<<'\n';
return 0;
}