2013年第四届蓝桥杯国赛试题及详解(Java本科A组)

蓝桥杯历年真题题目及题解目录汇总 

 

  1. 结果填空 (满分12分)
  2. 结果填空 (满分15分)
  3. 结果填空 (满分10分)
  4. 程序设计(满分16分)
  5. 程序设计(满分20分)
  6. 程序设计(满分27分)

 

 

1.标题:填算式

    请看下面的算式:

    (ABCD - EFGH) * XY = 900

    每个字母代表一个0~9的数字,不同字母代表不同数字,首位不能为0。

    比如,(5012 - 4987) * 36 就是一个解。

    请找到另一个解,并提交该解中 ABCD 所代表的整数。

    请严格按照格式,通过浏览器提交答案。
    注意:只提交 ABCD 所代表的整数,不要写其它附加内容,比如:说明性的文字。

答案:6048,全排

public class _01_填算式 {

	public static void main(String[] args) {
		dfs(0);
	}
	
	static int[] a = new int[] {0,1,2,3,4,5,6,7,8,9};
	
	static void dfs(int m) {
		if(m>=10) {
			int A = 1000*a[0]+100*a[1]+10*a[2]+a[3];
			int B = 1000*a[4]+100*a[5]+10*a[6]+a[7];
			int C = 10*a[8]+a[9];
			if((A-B)*C==900) {
				System.out.println(A+"-"+B+"  * "+C+"=="+900);
			}
			return;
		}
		
		for(int i=m;i<10;i++) {
			swap(i,m);
			dfs(m+1);
			swap(i,m);
		}
		
		
	}
	
	static void swap(int i,int j) {
		int t = a[i];
		a[i] = a[j];
		a[j] = t;
	}

}


2.标题:骰子迷题

    小明参加了少年宫的一项趣味活动:每个小朋友发给一个空白的骰子(它的6个面是空白的,没有数字),要小朋友自己设计每个面写哪个数字。但有如下要求:

    1. 每个面只能填写 0 至 8 中的某一个数字。

    2. 不同面可以填写同样的数字,但6个面总和必须等于24。

    填好后,小朋友可以用自己填写好数字的骰子向少年宫的两个机器人挑战----玩掷骰子游戏。规则如下:

    三方同时掷出自己的骰子,如果出现任何相同的数字,则三方都不计分。
  
    如果三方数字都不同,则最小数字一方扣 1 分,最大数字一方加 1 分。
   
    小明看到了两个机器人手中的骰子分别是:

    0 0 0 8 8 8
  
    1 1 4 5 6 7

    请你替小明算一下,他如何填写,才能使自己得分的概率最大。

    请提交小明应该填写的6个数字,按升序排列,数字间用一个空格分开。

    如果认为有多个答案,提交字母序最小的那个方案。

    请严格按照格式,通过浏览器提交答案。
    注意:只提交一行内容,含有6个被空格分开的数字。不要写其它附加内容,比如:说明性的文字。

 


3.标题:埃及分数

    古埃及曾经创造出灿烂的人类文明,他们的分数表示却很令人不解。古埃及喜欢把一个分数分解为类似: 1/a + 1/b 的格式。

    这里,a 和 b 必须是不同的两个整数,分子必须为 1

    比如,2/15 一共有 4 种不同的分解法(姑且称为埃及分解法):

1/8 + 1/120
1/9 + 1/45
1/10 + 1/30
1/12 + 1/20


    那么, 2/45 一共有多少个不同的埃及分解呢(满足加法交换律的算同种分解)? 请直接提交该整数(千万不要提交详细的分解式!)。

    请严格按照要求,通过浏览器提交答案。
    注意:只提交分解的种类数,不要写其它附加内容,比如:说明性的文字

答案:7,模拟,枚举的范围大一点比较稳,可以先试1000内,再10000,如果数没变大,基本是稳的

public class _03_埃及分数 {

	public static void main(String[] args) {
		int ans = 0;
		int n = 20000;
		for(int i=1;i<=n;i++)
			for(int j=i+1;j<=n;j++)
				if((i+j)/gcd(i+j,i*j)==2 && (i*j)/gcd(i+j,i*j)==45) {
					System.out.println("1/"+i+" + "+"1/"+j+" == 2/45");
					ans++;
				}
		System.out.println(ans);
	}
	
	static int gcd(int a,int b) {
		return b==0?a:gcd(b,a%b);
	}

}

 


4.标题:约数倍数选卡片

    闲暇时,福尔摩斯和华生玩一个游戏:
    
    在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:

    1,2,3, 6,12,18,24 ....

    当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。

    请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!

    当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。


    输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
    第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。

    程序则输出必胜的招法!!


例如:
用户输入:
2 3 6
3 6
则程序应该输出:
3

再如:
用户输入:
1 2 2 3 3 4 5
3 4 5
则程序应该输出:
4


资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗  < 2000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
 

代码里面有很详细的注释了,博弈,dfs解决 ,思路都是枚举所有对手的情况,如果都不能必胜,那么你就是win

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class _04_约数倍数选卡片 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String[] s1 = in.nextLine().split(" ");
		String[] s2 = in.nextLine().split(" ");

		for(int i=0;i<=100;i++)
			g[i] = new ArrayList<>();
		for(String s:s1)
			if(s!="")
				num[Integer.parseInt(s)]++;
		for(String s:s2)
			if(s!="")
				choice.add(Integer.parseInt(s));
		
		for(int i=1;i<=100;i++)
			if(num[i]>0) {
				num[i]--;
				for(int j=1;j<=100;j++)
					if(num[j]>0 &&(i%j==0 || j%i==0))
						g[i].add(j);
				num[i]++;
			}
		
		int flag = -1;
		Collections.sort(choice);//排序,从小到大找答案
		for(int x:choice) {
			num[x]--;//自己先选一张,再给对手选,对手没得选你win
			if(dfs(x)==1) {
				flag = x;
				break;
			}
			num[x]++;
		}
		
		System.out.println(flag);
	}
	
	static int[] num = new int[105];//记录0-100的卡片各有多少
	static ArrayList g[] = new ArrayList[105];//预处理,每一个数能选的下一个数,有点像建图
	static ArrayList choice = new ArrayList<>();//第一张的可选项
	
	static int dfs(int u) {
		
		for(int i=g[u].size()-1;i>=0;i--) {//果然是逆着遍历才能AC,至于为什么我不知道
			int v = g[u].get(i);
			if(num[v]>0) {
				num[v]--;
				int win = dfs(v);//先记录输赢,直接return,回溯会导致失效
				num[v]++;
				if(win==1)//对方赢了,你还不是输了吗?
					return -1;
			}
		}
		
		return 1;//上面枚举了那么多,对手都没赢,那你就是赢了
	}

}


5.标题:网络寻路

    X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。

    源地址和目标地址可以相同,但中间节点必须不同。

    如图1所示的网络。

    1 -> 2 -> 3 -> 1  是允许的
    
    1 -> 2 -> 1-> 2 或者 1->2->3->2 都是非法的。

    输入数据的第一行为两个整数N M,分别表示节点个数和连接线路的条数(1<=N<=10000; 0<=M<=100000)。
    接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。

    输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。


    输出一个整数,表示满足要求的路径条数。

例如:
用户输入:
3 3
1 2
2 3
1 3
则程序应该输出:
6


再例如:
用户输入:
4 4
1 2
2 3
3 1
1 4
则程序应该输出:
10


资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗  < 2000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

2013年第四届蓝桥杯国赛试题及详解(Java本科A组)_第1张图片

dfs+回溯,c++才能在官网AC,要么拿去c语言网A一遍,官网只有c的测试规模 ,这题就是枚举每个点走3步,中途不能回祖先点,这里可以不标记出发点,这样最后可以回到出发点,那么问题来了,如果不标记出发点,第二步可能回到出发点,所以我们要记录它上一个过来的节点,这样第三个点就不会是出发点了,第四点是什么我们不会关心,只要不是标记过的点就行

import java.util.ArrayList;
import java.util.Scanner;

public class 网络寻路 {//c++才能在官网AC

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		m = in.nextInt();
		g = new ArrayList[n+5];
		vis = new boolean[n+5];
		for(int i=0;i<=n;i++)
			g[i] = new ArrayList<>();
		for(int i=1;i<=m;i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			g[a].add(b);
			g[b].add(a);
		}
		
		for(int i=1;i<=n;i++) 
			dfs(i,-1,3);//模拟转发2次到再到目的,共走3次
		
		System.out.println(ans);
	}
	
	static int n,m,ans=0;
	static ArrayList[] g;
	static boolean[] vis;
	
	static void dfs(int u,int fa,int step) {
		if(step==0) {
			ans++;
			return;
		}
		
		for(int v:g[u]) 
			if(!vis[v] && v!=fa) {
				vis[v] = true;
				dfs(v,u,step-1);
				vis[v] = false;
			}
	}

}


6.标题:公式求值

    输入n, m, k,输出图1所示的公式的值。其中C_n^m是组合数,表示在n个人的集合中选出m个人组成一个集合的方案数。组合数的计算公式如图2所示。

    输入的第一行包含一个整数n;第二行包含一个整数m,第三行包含一个整数k。

    计算图1所示的公式的值,由于答案非常大,请输出这个值除以999101的余数。

【样例输入1】
3
1
3
【样例输出1】
162

【样例输入2】
20
10
10
【样例输出2】
359316

【数据规模与约定】
对于10%的数据,n≤10,k≤3;
对于20%的数据,n≤20,k≤3;
对于30%的数据,n≤1000,k≤5;
对于40%的数据,n≤10^7,k≤10;
对于60%的数据,n≤10^15,k ≤100;
对于70%的数据,n≤10^100,k≤200;
对于80%的数据,n≤10^500,k ≤500;
对于100%的数据,n在十进制下不超过1000位,即1≤n<10^1000,1≤k≤1000,同时0≤m≤n,k≤n。

【提示】
999101是一个质数;
当n位数比较多时,绝大多数情况下答案都是0,但评测的时候会选取一些答案不是0的数据;

资源约定:
峰值内存消耗(含虚拟机) < 128M
CPU消耗  < 2000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。


2013年第四届蓝桥杯国赛试题及详解(Java本科A组)_第2张图片

 

 

 

你可能感兴趣的:(蓝桥杯)