0
点赞
收藏
分享

微信扫一扫

题目 1886: 蓝桥杯2017年第八届真题-包子凑数

时间限制: 1Sec 内存限制: 128MB 提交: 2378 解决: 789

题目描述

       小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

        每当有顾客想买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 <= Ai <= 100)

输出

一个整数代表答案。如果凑不出的数目有无限多个,输出INF。

样例输入复制

2
4
5

样例输出复制

6

        阅读完此题 很多同学都特别的苦恼,这该如何下手呢,很多同学都会从暴力下手,然而这道题用暴力是固然不行的。其实2017年的这道题与2013年蓝桥杯的某一道特别类似,不知道同学们发现了没有了。17年这道题目叫做凑不出的包子,13年那道题叫做凑不出的数。其思想核心是不变的,接下来我来谈谈如何解决这类题型,希望有获得帮助的同学为我点点赞,你的点赞是我不断更新的动力 ~.~

        首先我们对输入样例2 4 5进行分析,2是代表有两个整数,那么4 5 不能凑出哪些数呢,我们通过简单的计算如下

        然后我们会发现如下规律:

 

        我们会发现,4 5这两个数除了1 2 3 6 7 11这六个数,其他都能凑出来,我们再来看看4 6 这两个数,它们不能凑出哪些数呢?这想都不用想,首先都一点,它们连所有的奇数都凑不来,为什么这么说呢,因为这两个数是偶数 4x+6y 的结果也必然是偶数,所以根本无法凑出奇数,所以凑不出的数有无限个。

        综上这一点我们会发现,如果两个数的公约数都不为1,那么必然凑不出的数有无限个的 !这一点是毫无疑问的,所以我们可以先对N个数进行gcd()求公约数,这种方法又叫辗转相除法求公约数,如下

        

        然后我们再来来了解一点,那就是,如果4是能被凑出来的,那么4+4等于8, 8也必然是能凑出来的,因为8能凑出来,那么8+4等于12,12也是可以凑出来的,以此类推16,20,24...也都是可以凑出来的,知道了这些那么,接下来就附上代码啦,如下:

package test;
import java.util.*;
public class Main {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int N=sc.nextInt();
		int[] arr=new int[N];
		int zhi=0;
		boolean[] f=new boolean[10000];  //定义数组f,此数组为布尔型数组,用了表示当前的索引能否凑出来,凑出来就为true,否则为false
		f[0]=true;  //并定义首个索引为true
		for(int i=0;i<N;i++) {
			arr[i]=sc.nextInt();
		
			if(i==0) {
				zhi=arr[0];
			}
			else {			//求arr数组中所有元素的公约数
				zhi=gcd(arr[i],zhi);
			}
			for(int j=0;j<10000-arr[i];j++) {	
				if(f[j]) {	//以此递归,例如当f[0]为真,那么f[4+0]=true,即4能凑出来,以此类推,当f[4]=true,那么f[4+4]=true,所以8凑出来,以此类推12,16,20均可以凑出来
					f[arr[i]+j]=true;
				}
			}		
		}
		if(zhi!=1) {  //如果arr数组中所有元素的公约数不等于1,那么必然凑不出偶数,则输出“INF”
			System.out.println("INF");
			return;
		}
		int count=0;
		for(int i=0;i<10000;i++) {
			if(f[i]==false) count++; 
		}
		System.out.println(count);
	}
	public static int gcd(int a,int b) {    //利用辗转相除法求公约数
		if(b==0) {
			return a;
		}
		else {
			return gcd(b,a%b);
		}
	}
}

如果小伙伴有更好的奇思妙想,绝世武功,欢迎在留言区留下你的足迹哦 ~.~

举报

相关推荐

0 条评论