题目一看,是个 组合问题,是完全背包问题的变形:有几个物品,每个物品无限个,每个物品选任意个,能否凑到某个重量。
但是,题目说会出现有无限个数被凑不出来的, 说明这些数的$gcd$不是1。
这里用到裴蜀定理 ,任意两个数的组合必定是他们$gcd$的任意两个数的组合必定是他们$gcd的倍数$,同样可以推广到更多数:如果这些数的$gcd$是$d$,那么他们的组合是$d$的倍数,如果$d$不是$1$,那么必然有无限个数无法被组合出来。
#include<iostream>
using namespace std;
const int N = 110;
int w[N];
bool dp[N][10005]; // 10000最枚举的最大价值,dp[i][j]表示前i个物品能否凑出j
int gcd(int a,int b)
{
return b == 0 ? a : gcd(b,a%b);
}
int main()
{
int n;
cin >> n;
int g = 0;
for(int i = 1;i <= n;i++)
{
cin >> w[i];
g = gcd(w[i],g);
}
dp[0][0] = true;
if(g==1)
{
for(int i = 1;i <= n;i++)
{
for(int j = 0; j <= 10000;j++)
{
if(dp[i-1][j] == true) dp[i][j] = true;
else if(j >= w[i]) dp[i][j] = dp[i][j-w[i]];
}
}
// 一共有n件物品
int ans = 0;
for(int i = 1;i <= 10000;i++)
{
if(dp[n][i] == false) ans++;
}
cout << ans;
}
else cout << "INF";
return 0;
}