第六届蓝桥杯JavaA组解析(2015年)
- 1-熊怪吃核桃
- 森林里有一只熊怪,很爱吃核桃,不过它有哥习惯,每次会把找到的核桃分成相等的两份
- 吃掉一份,留一份,如果不能等分,熊怪就会扔掉一个核桃再分,第二天再继续这个过程,
- 直到最后剩余一个核桃,直接丢掉。
- 有一天,熊怪发现了1543哥核桃,请问它在吃核桃的过程中,一共要丢掉多少核桃。
/**
* 1-熊怪吃核桃
* 森林里有一只熊怪,很爱吃核桃,不过它有哥习惯,每次会把找到的核桃分成相等的两份
* 吃掉一份,留一份,如果不能等分,熊怪就会扔掉一个核桃再分,第二天再继续这个过程,
* 直到最后剩余一个核桃,直接丢掉。
* 有一天,熊怪发现了1543哥核桃,请问它在吃核桃的过程中,一共要丢掉多少核桃。
*/
public class Main {
public static void main(String[] args) {
int num = 1543;
int count = 1 ; //最后一个直接丢掉
while(num > 1){
if(num > 1){
if(num % 2 ==1) {
count++;
}
num /= 2 ;
}else{
break ;
}
}
System.out.println(count);
}
}
- 2.星系炸弹
- 在X星系的广袤空间中漂浮着许多X星人造炸弹,用来作为宇宙的路标,每个炸弹都可以设置多少天之后爆炸
- 比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸.
- 有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期
- 请填写该日期,格式为yyyy-mm-dd 即4位年份2位月份2位日期。比如:2015-02-19请严格按照格式书写。不能出现其它文字或符号。
/**
* 2.星系炸弹
* 在X星系的广袤空间中漂浮着许多X星人造炸弹,用来作为宇宙的路标,每个炸弹都可以设置多少天之后爆炸
* 比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸.
* 有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期
*
* 请填写该日期,格式为yyyy-mm-dd 即4位年份2位月份2位日期。比如:2015-02-19请严格按照格式书写。不能出现其它文字或符号。
*
*/
public class Main {
public static void main(String[] args) {
int t = 1000 - 365 - 366 - 21 - 31;
int month = 1;
while(t > 0){
switch (month){
case 1: case 3: case 5: case 7: case 8:case 10: case 12: t -= 31; month ++ ; break;
case 2: t -= 28; month++; break;
case 4: case 6: case 9: case 11: t-= 30; month++; break;
}
}
System.out.println("2017-"+ "0" + (month-1) + "-" + "0" + (t+31) );
}
}
- 3.九数分三组,1~9的数字可以组成3个3位数,设为A,B,C
- 现在要求满足如下关系:
- B = 2 * A
- C = 3 * A
- 请写出A的所有可能答案,数字间按空格排列,数字按照升序排列
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
/**
* 3.九数分三组,1~9的数字可以组成3个3位数,设为A,B,C
* 现在要求满足如下关系:
* B = 2 * A
* C = 3 * A
* 请写出A的所有可能答案,数字间按空格排列,数字按照升序排列
*/
public class Main {
public static boolean equal(int a, int b, int c){
int x1 = a / 100;
int y1 = (a / 10) % 10 ;
int z1 = a % 10 ;
int x2 = b / 100;
int y2 = (b / 10) % 10 ;
int z2 = b % 10 ;
int x3 = c / 100;
int y3 = (c / 10) % 10 ;
int z3 = c % 10 ;
int [] res = {x1,x2,x3,y1,y2,y3,z1,z2,z3} ;
Arrays.sort(res);
String s = "" ;
for(int i=0; i<res.length; i++){
s += res[i] ;
}
if(s.equals("123456789")){
return true ;
}else{
return false ;
}
}
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>() ;
for(int i=100; i<=999; i++){
for( int j=100; j<=999; j++){
for(int k=100; k<=999; k++){
if((j == 2*i) && (k == 3*i)){
if(equal(i,j,k)) {
set.add(i);
}
}
}
}
}
Iterator<Integer> iterator = set.iterator() ;
while(iterator.hasNext()){
System.out.print(iterator.next() + " ");
}
}
}
- 4-循环节长度
- 两个整数做除法,有时候会产生循环小数,其循环部分称为循环节,
- 下面方法可以求出循环节的长度,仔细阅读代码,填写空白处的代码
import java.util.Vector;
/**
* 4-循环节长度
* 两个整数做除法,有时候会产生循环小数,其循环部分称为循环节,
* 下面方法可以求出循环节的长度,仔细阅读代码,填写空白处的代码
*/
public class Main {
public static int f(int n, int m){
n = n % m ;
Vector v = new Vector() ;
for(;;){
v.add(n) ;
n *= 10 ;
n = n % m ;
if(n == 0){
return 0 ;
}
if(v.indexOf(n) >= 0){
return v.size() - v.indexOf(n) ;
}
}
}
public static void main(String[] args) {
System.out.println(f(11,13));
}
}
5.打印菱形:略
- 6.加法变乘法
- 我们都知道1+2+3+…+49=1225
- 我们现在要求将其中的不相邻的两个加号变成乘号,使得结果等于2015
- 寻找另一个答案,把位置靠左的乘号左边的那个数字提交。
/**
* 6.加法变乘法
* 我们都知道1+2+3+...+49=1225
* 我们现在要求将其中的不相邻的两个加号变成乘号,使得结果等于2015
* 寻找另一个答案,把位置靠左的乘号左边的那个数字提交。
*/
public class Main {
public static void main(String[] args) {
for(int i=1; i<=46; i++){
for(int j=i+2; j<=48; j++){
if(i*(i+1)+j*(j+1)-(i+i+1)-(j+j+1) == 2015-1225){
System.out.println(i + " " + j);
}
}
}
}
}
- 7.牌型种数
- 小明被劫持到X赌城,被迫与其它三人玩牌,
- 一副扑克牌,去掉大小王,共52张,均匀的发给4个人,每个人13张,
- 这时候小明的脑子里突然冒出一个问题:如果不考虑花色,只考虑点数,也不考虑自己得到牌的先后顺序,
- 自己手里能拿到的初始牌型组合有多少种呢?
/**
* 7.牌型种数
* 小明被劫持到X赌城,被迫与其它三人玩牌,
* 一副扑克牌,去掉大小王,共52张,均匀的发给4个人,每个人13张,
* 这时候小明的脑子里突然冒出一个问题:如果不考虑花色,只考虑点数,也不考虑自己得到牌的先后顺序,
* 自己手里能拿到的初始牌型组合有多少种呢?
*/
public class Main {
static int count = 0;
/**
*
* @param k 牌型的种类数,1-13
* @param cnt 一共抽了多少张牌
*/
public static void f(int k, int cnt){
if(k>13 || cnt>13){
return ;
}
if(k==13 && cnt==13){
count ++ ;
}
for(int i=0; i<5; i++){ //每种牌型出现的次数为0-4次
f(k+1, cnt+i) ;
}
}
public static void main(String[] args) {
f(0, 0) ;
System.out.println(count);
}
}
- 8.移动距离
- X星球的居民小区楼房全是一样的,并且按矩阵样式排列,其楼房编号为1,2,3…
- 当排满一行时,从下一行相邻的楼往反方向排。
- 我们已知两个楼号m和n,需要求出它们之间的最短移动距离,不能沿着斜线方向移动,
- 输入为3个整数,w,m,n,空格分开,都在1-10000范围内,
- w为排号宽度,m,n为待计算的楼号,要求输出一个数,表示m和n之间的最短移动距离。
import java.util.Scanner;
/**
* 8.移动距离
* X星球的居民小区楼房全是一样的,并且按矩阵样式排列,其楼房编号为1,2,3...
* 当排满一行时,从下一行相邻的楼往反方向排。
* 我们已知两个楼号m和n,需要求出它们之间的最短移动距离,不能沿着斜线方向移动,
* 输入为3个整数,w,m,n,空格分开,都在1-10000范围内,
* w为排号宽度,m,n为待计算的楼号,要求输出一个数,表示m和n之间的最短移动距离。
*/
public class Main {
/**题目本身没有考算法,但是逻辑性比较强,当然就是行列对应相减取绝对值后求和
* 主要的难点在于根据行数求出对应的列数。
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int w = input.nextInt();
int m = input.nextInt();
int n = input.nextInt();
int rm = m % w == 0 ? m / w : m / w + 1;
int rn = n % w == 0 ? n / w : n / w + 1;
int cm, cn;
if (rm % 2 == 0) {
cm = rm * w - m + 1;
} else {
cm = w - (rm * w - m);
}
if(rn % 2 == 0){
cn = rn * w - n + 1 ;
}else{
cn = w - (rn * w - n) ;
}
System.out.println(Math.abs((rm-rn))+ Math.abs(cm-cn));
}
}
- 9.垒筛子 (递归法)
- 赌圣atm晚年迷恋上垒骰子,就是把筛子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体
- 经过长期观察,atm发现了稳定筛子的奥秘,有些数字的面贴合着会相互排斥,
- 我们先来规范一下筛骰子:1的对面是4;2的对面是5;3的对面是6
- 假设有m组互斥现象,每组中的那两个数字面紧贴在一起,骰子就不能稳定的垒起来
- atm想计算一下一共有多少种不同的可能的垒骰子的方式
- 两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同,
import java.util.Scanner;
/**
* 9.垒筛子
* 赌圣atm晚年迷恋上垒骰子,就是把筛子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体
* 经过长期观察,atm发现了稳定筛子的奥秘,有些数字的面贴合着会相互排斥,
* 我们先来规范一下筛骰子:1的对面是4;2的对面是5;3的对面是6
* 假设有m组互斥现象,每组中的那两个数字面紧贴在一起,骰子就不能稳定的垒起来
* atm想计算一下一共有多少种不同的可能的垒骰子的方式
* 两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同,
*
*/
public class Main {
static int [] op = new int [7] ;
static long count = 0 ;
static int mod = 1000000007 ;
static boolean [][] conflict = new boolean [7][7] ;
public static void init(){ //初始化对面
op[1] = 4;
op[2] = 5;
op[3] = 6;
op[4] = 1;
op[5] = 2;
op[6] = 3;
}
/**
* 上层定好骰子朝上数字为up的情况下,垒好cnt个骰子的方案数
* @param up 上面
* @param cnt 还有cnt个骰子要组合
* @return
*/
public static long f(int up, int cnt){
long ans = 0 ;
if(cnt == 0){ //n个骰子都已经定位,递归出口
return 4 ;
}
for(int up1=1; up1<=6; up1++){//下层递归
if(conflict[op[up]][up1]){ //冲突不可选为上面
continue;
}
ans = (ans + f(up1, cnt-1)) % mod ;
}
return ans ;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
init() ;
int n = input.nextInt() ; //骰子数
int m = input.nextInt() ; //行数
for(int i=0; i<m; i++){
int a = input.nextInt() ;
int b = input.nextInt() ;
conflict[op[a]][b] = true ;
conflict[op[b]][a] = true ;
}
for(int up=1; up<=6; up++){
count = (count + 4 * f(up, n-1)) % mod ;
}
System.out.println(count);
}
}
9.垒筛子 (动态规划法)
import java.util.Scanner;
public class Main1 {
static long mod = 1000000007;
static int [] op = new int [7] ;
static long [][] dp = new long [2][7] ; //第i层j朝上的合法方案数
static void init(){
op[1] = 4 ;
op[2] = 5 ;
op[3] = 6 ;
op[4] = 1 ;
op[5] = 2 ;
op[6] = 3 ;
}
static boolean [][] conflict = new boolean[7][7] ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
init() ;
int n = input.nextInt() ; //骰子数
int m = input.nextInt() ; //行数
for(int i=0; i<m; i++){
int a = input.nextInt() ;
int b = input.nextInt() ;
conflict[op[a]][b] = true ;
conflict[op[b]][a] = true ;
}
for(int j=1; j<=6; j++){
dp[0][j] = 1 ;
}
int cur = 0 ;
for(int level=2; level<=n; level++){ //迭代的层数
cur = 1 - cur ; //0-1滚动数组
//参试者将六个面放到当前层朝上的方向
for(int j=1; j<=6; j++){
dp[cur][j] = 0 ;
for(int i=1; i<=6; i++){
if(conflict[i][op[j]]){
continue;
}
dp[cur][j] = (dp[cur][j] + dp[1-cur][i]) % mod ; //自底向上的过程
}
}
}
long sum = 0 ;
for(int k=1; k<=6; k++){
sum = (sum + dp[cur][k]) % mod ;
}
long ans = 1;
long temp = 4;
long p = n ;
while(p != 0){ //快速幂求解4的n次方
if((p&1) == 1){
ans = (ans * temp) ;
}
temp = (temp*temp) % mod ;
p >>= 1 ;
}
System.out.println(sum * ans);
}
}
10.灾后重建(略)