1226. 包子凑数 数学 dp 完全背包
小明几乎每天早晨都会在一家包子铺吃早餐。
他发现这家包子铺有 N 种蒸笼,其中第 i 种蒸笼恰好能放 Ai 个包子。
每种蒸笼都有非常多笼,可以认为是无限笼。
每当有顾客想买 X 个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有 X 个包子。
比如一共有 3 种蒸笼,分别能放 3、4 和 5 个包子。
当顾客想买 11 个包子时,大叔就会选 2 笼 3 个的再加 1 笼 5 个的(也可能选出 1 笼 3 个的再加 2 笼 4 个的)。
当然有时包子大叔无论如何也凑不出顾客想买的数量。
比如一共有 3 种蒸笼,分别能放 4、5 和 6 个包子。
而顾客想买 7 个包子时,大叔就凑不出来了。
小明想知道一共有多少种数目是包子大叔凑不出来的。
输入格式
第一行包含一个整数 N。
接下来 N 行,每行包含一个整数 Ai。
输出格式
输出一个整数代表答案。
如果凑不出的数目有无限多个,输出INF。
数据范围
1≤N≤100,
1≤Ai≤100
输入样例1:
2
4
5
输出样例1:
6
输入样例2:
2
4
6
输出样例2:
INF
样例解释
对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。
对于样例2,所有奇数都凑不出来,所以有无限多个。
1.判断是否INF:
由定理:n个数能凑出的最小正整数为他们的最大公约数d,如果d==1,那么可以凑出任何数(包含个数为负的情况),如果n个数的最大公约数d不为1,那么非d的倍数都凑不出来,即有INF个
2.d==1判断出是有限个的情况下,用dp,f[i][j]表示前i个数是否能凑出j
3.递推关系:f[i][j]=f[i-1][j-k(a[i])]k个相或
==>f[i][j]=f[i-1][j]|f[i][j-a[i]] //前提是j>=a[i]
一般思路,空间复杂度比较大
import java.util.*;
public class Main{
static int N=105,d;
static int a[]=new int [N];
static boolean f[][]=new boolean [N][10005];//经验值:由于ai最大为100,所以凑不出的正整数最大为1e4
static int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
public static void main(String []args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
for(int i=1;i<=n;++i){
a[i]=sc.nextInt();
if(i==1)d=a[i];
else d=gcd(d,a[i]);
}
if(d!=1){
System.out.println("INF");
return ;
}
f[0][0]=true;
for(int i=1;i<=n;++i){
for(int j=0;j<10005;++j){
f[i][j]|=f[i-1][j];
if(j>=a[i])f[i][j]|=f[i][j-a[i]];
}
}
int ans=0;
for(int j=0;j<10005;++j){
if(f[n][j]==false)ans++;
}
System.out.println(ans);
}
}
可以优化空间
import java.util.*;
public class Main{
static int N=105,d;
static int a[]=new int [N];
static boolean f[]=new boolean [10005];//经验值:由于ai最大为100,所以凑不出的正整数最大为1e4
static int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
public static void main(String []args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
for(int i=1;i<=n;++i){
a[i]=sc.nextInt();
if(i==1)d=a[i];
else d=gcd(d,a[i]);
}
if(d!=1){
System.out.println("INF");
return ;
}
f[0]=true;
for(int i=1;i<=n;++i){
for(int j=a[i];j<10005;++j){
f[j]|=f[j-a[i]];
}
}
int ans=0;
for(int j=0;j<10005;++j){
if(f[j]==false)ans++;
}
System.out.println(ans);
}
}