问题描述:
小明几乎每天早晨都会在一家包子铺吃早餐,他发现这家包子铺有N种蒸笼,其中第i种蒸笼都有非常多种,可以认为是无限种。
每当有顾客想买x种包子,卖包子的大叔都会迅速选出若干笼包子来,使得这若干笼包子中恰好有X个包子。比如一共有3种蒸笼,分别能放3、4、5个包子。当顾客想买11个时,大叔就会选2笼3个的再加1笼5个的(也可能选出1笼3个的再加2笼4个的)。
当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有3种蒸笼,分别能放4、5和6个包子。而顾客想买7个包子时,大叔就奏不出来了。
小明想知道一共有多少种数目是包子大叔凑不出来的。
输入格式:
第一行包含一个整数N。(1 <= N<= 100)
以下N行每行包含—个整数Ai。(1 <= Aic= 100)
输出格式:
一个整数代表答案。如果凑不出的数目有无限多个,输出INF。
代码:
import java.io.*;
import java.util.Arrays;
public class Main {
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st=new StreamTokenizer(br);
public static void main(String[] args) throws Exception {
int n = nextInt();
int[] arr = new int[101];
Arrays.fill(arr, 999);
int t, s = 0;
for (int i = 0; i < n; i++) {
t = nextInt();
if (arr[t] == 999) {
arr[t] = t;
s++;
}
}
Arrays.sort(arr);//排序
if (arr[0]==1){
System.out.println(0);
return;
}
int k = 10001;
for (int i=0;i<s-1;i++){
for (int j=1;j<s;j++){
if(gcd(arr[i],arr[j])==1){
k=Math.min(k,arr[i]*arr[j]);
}
if (k==arr[i]*arr[j]||arr[i]*arr[j+1]>=k)
break;
}
if (arr[i]*arr[i+1]>=k){
break;
}
}
int []sk=new int[101];
for (int i=0;i<s;i++){
for (int j=2;j<=arr[i];j++){
if (arr[i]%j==0){
sk[j]++;
}
}
}
Arrays.sort(sk);
if (k>10000&&sk[100]==n){
System.out.println("INF");
return;
}
int []crr=new int[k+1];
int []drr=new int[k+1];
int m=0,co,ss;
for (int i=0;i<s;i++){
co=m;
for (int y=0;y<co;y++){
for (int j=1;j<=(k-drr[y])/arr[i];j++){
ss=drr[y]+arr[i]*j;
if (crr[ss]==0){
crr[ss]=ss;
drr[m]=ss;
m++;
}
}
}
for (int j=1;j<=k/arr[i];j++){
if (arr[i]*j>k){
break;
}
if (crr[arr[i]*j]==0){
drr[m]=arr[i]*j;
crr[arr[i]*j]=arr[i]*j;
m++;
}
}
}
System.out.println(k-m);
}
static int nextInt() throws Exception{
st.nextToken();
return (int)st.nval;
}
public static int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
}