第六届蓝桥杯JavaA组解析(2015年)

第六届蓝桥杯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.灾后重建(略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值