Step1 Problem:
Alice和Bob玩了无数局博弈觉得有点枯燥,于是他们想买一台售价为n元的switch,在switch上一较高下。他们东拼西凑出了m种面额的钱币,每种面额的钱币有无限张,问凑出n元的方案数。
当n=4时,我们认为{1,1,2},{1,2,1},{2,1,1}为同一种方案。
数据范围:
长度不超过 50 位的实数 n (1<=n<= 500), 整数 m (1<=m<=30), 带有一位小数的实数或整数 a[i] (0 <= a[i] <= 50)
Step2 Ideas:
长度不超过 50 位,输入得用字符串。
如果 s 为包含小数点后两位,那么无论如何都构成不了。
然后我们可以对数都乘 10,这样就不存在小数了。
然后就是一个 完全背包,求和 = n 的方案数;
Step3 Code:
#include<bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
int v[50], dp[6000];
int main()
{
int n, m;
char s[100];
while(~scanf("%s %d", s, &m))
{
double x;
for(int i = 0; i < m; i++)
{
scanf("%lf", &x);
v[i] = x*10;
}
int len = strlen(s);
int flag = 0, num = 0;
for(int i = 0; i < len; i++)
{
if(flag) num++;
if(s[i] == '.') flag = 1;
}
if(num >= 2) {
printf("0\n");
continue;
}
else {
n = 0;
for(int i = 0; i < len; i++)
{
if(s[i] == '.') continue;
n = n*10 + s[i] - '0';
}
if(num == 0) n *= 10;
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 0; i < m; i++)
{
for(int j = v[i]; j <= n; j++)//完全背包
{
dp[j] += dp[j-v[i]];
dp[j] %= MOD;
}
}
printf("%d\n", dp[n]);
}
}
return 0;
}