2016年第七届蓝桥杯省赛Java B组真题+个人题解

目录

一、煤球数目

二、生日蜡烛

三、凑算式

六、方格填数

七、剪邮票

八、四平方和

九、取球博弈

十、压缩变换


一、煤球数目

蓝桥杯官网_煤球数量

 思路:

分析可知: 每一层的煤球数量=上一层的煤球数量+当前层数

答案:

171700

代码:

import java.io.IOException;
import java.io.PrintWriter;

public class Main {
    static PrintWriter pw=new PrintWriter(System.out);
    static int a[]=new int[110];//存储每层的煤球个数
    public static void main(String args[]) throws IOException{
        int res=0;
        for(int i=1;i<=100;i++){
            a[i]=a[i-1]+i;
            res+=a[i];
        }
        pw.println(res);
        pw.close();
    }
}

二、生日蜡烛

蓝桥杯官网_生日蜡烛

 思路:

设开始生日party时年龄为x,一共举办了n次,则吹熄的蜡烛数为x、x+1、x+2、x+3 ····x+n-1,共nx+n(n-1)/2,枚举x和n使其等于236即可

 答案:

26

代码:

import java.io.IOException;
import java.io.PrintWriter;

public class Main {
    static PrintWriter pw=new PrintWriter(System.out);
    public static void main(String args[]) throws IOException{
        for(int n=1;n<=100;n++){
            for(int x=1;x<=100;x++){
                if(n*(n-1)%2==0 && n*x+n*(n-1)/2==236)
                    pw.println(x);
            }
        }
        pw.close();
    }
}

三、凑算式

蓝桥杯官网_凑算式

该官网题目出错了,原题中A~I代表1~9的数字而不是0~9的数字

 思路:

由6+8/3+952/714=10可知,不能直接利用整数除法下取整来做,将两个分式进行通分
因此将等式转变为  A+(B*(GHI)+C*(DEF))/(C*(GHI))=10 且 (B*(GHI)+C*(DEF))必须是(C*(GHI))的整数倍

答案:

29

代码:

import java.io.IOException;
import java.io.PrintWriter;

public class Main{
    static PrintWriter pw=new PrintWriter(System.out);
    static int N=20;
    static int a[]=new int[N];
    static boolean flag[]=new boolean[N];
    static int res=0;
    public static boolean check(){
        int x1=a[0];
        int x2=a[1];
        int x3=a[2];
        int x4=a[3]*100+a[4]*10+a[5];
        int x5=a[6]*100+a[7]*10+a[8];
        if((x2*x5+x3*x4)%(x3*x5)==0 && x1+(x2*x5+x3*x4)/(x3*x5)==10) return true;
        return false;
    }
    public static void dfs(int u){
        if(u==9){
            if(check()) res++;
            return;
        }
        for(int i=1;i<=9;i++){
            if(!flag[i]){
                flag[i]=true;
                a[u]=i;
                dfs(u+1);
                flag[i]=false;
            }
        }
    }
    public static void main(String args[]) throws IOException{
        dfs(0);
        pw.println(res);
        pw.close();
    }
}

六、方格填数

蓝桥杯官网_方格填数

 思路:

dfs枚举全排列,分别判断每种情况是否相邻
判断是否相邻,即查看这两个位置的数的绝对值的差是否为1

 答案:

1580

代码:

import java.io.IOException;
import java.io.PrintWriter;

public class Main {
    static PrintWriter pw=new PrintWriter(System.out);
    static int N=10;
    static int a[]=new int[N];
    static boolean flag[]=new boolean[N];
    static int res=0;
    public static boolean check(){
        if(Math.abs(a[0]-a[1])==1) return false;
        if(Math.abs(a[0]-a[3])==1) return false;
        if(Math.abs(a[0]-a[4])==1) return false;
        if(Math.abs(a[0]-a[5])==1) return false;
        if(Math.abs(a[1]-a[2])==1) return false;
        if(Math.abs(a[1]-a[4])==1) return false;
        if(Math.abs(a[1]-a[5])==1) return false;
        if(Math.abs(a[1]-a[6])==1) return false;
        if(Math.abs(a[2]-a[5])==1) return false;
        if(Math.abs(a[2]-a[6])==1) return false;
        if(Math.abs(a[3]-a[4])==1) return false;
        if(Math.abs(a[3]-a[7])==1) return false;
        if(Math.abs(a[3]-a[8])==1) return false;
        if(Math.abs(a[4]-a[5])==1) return false;
        if(Math.abs(a[4]-a[7])==1) return false;
        if(Math.abs(a[4]-a[8])==1) return false;
        if(Math.abs(a[4]-a[9])==1) return false;
        if(Math.abs(a[5]-a[6])==1) return false;
        if(Math.abs(a[5]-a[8])==1) return false;
        if(Math.abs(a[5]-a[9])==1) return false;
        if(Math.abs(a[6]-a[9])==1) return false;
        if(Math.abs(a[7]-a[8])==1) return false;
        if(Math.abs(a[8]-a[9])==1) return false;
        return true;
    }
    public static void dfs(int u){
        if(u==10){
            if(check()) res++;
            return;
        }
        for(int i=0;i<=9;i++){
            if(!flag[i]){
                flag[i]=true;
                a[u]=i;
                dfs(u+1);
                flag[i]=false;
            }
        }
    }
    public static void main(String args[]) throws IOException{
        dfs(0);
        pw.println(res);
        pw.close();
    }
}

七、剪邮票

蓝桥杯官网_剪邮票

 思路:

将原题重新进行编码,转换的数的下标如上图所示,便于判断两点是否相连(两个数的绝对值相差1或者5即代表相连)
dfs枚举五个数,共 C_{12}^{5}=792种情况,判断每种情况的五个数字都相连即可
判断五个数字是否相连,利用并查集的思想,若两个数相连,则将其合并,最后判断这五个数是否合并为一堆,若为1则代表这五个数相连

相连的情况,最后合并为一堆,即连通块数量为1

 不相连情况,最后堆数大于1,即连通块数量大于1

答案:

116

 代码:

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class Main {
    static PrintWriter pw=new PrintWriter(System.out);
    static int N=20;
    static int b[]={1,2,3,4,6,7,8,9,11,12,13,14};
    static boolean flag[]=new boolean[N];
    static int a[]=new int[N];
    static int c[]=new int[N];
    static int p[]=new int[N];
    static Set<Integer>set=new HashSet<>();
    public static int find(int x){//并查集
        if(p[x]!=x) p[x]=find(p[x]);
        return p[x];
    }
    public static boolean check(int c[]){
        for(int i=0;i<5;i++) p[i]=i;
        for(int i=0;i<5;i++){
            for(int j=i+1;j<5;j++){
                if((find(i)!=find(j)) && (Math.abs(c[i]-c[j])==5 || Math.abs(c[i]-c[j])==1)){
                    p[find(j)]=find(i);//合并
                }
            }
        }
        int res=0;
        for(int i=0;i<5;i++){//查找一共有几堆
            if(p[i]==i) res++;
        }
        return res==1;
    }
    public static void dfs(int u){
        if(u==5){
            c=Arrays.copyOf(a,5);//由于次数是C12 5而不是A12 5,因此不考虑顺序,将这五个数进行排序
            Arrays.sort(c,0,5);
            int x=c[0]*10000+c[1]*1000+c[2]*100+c[3]*10+c[4];
            if(check(c)) set.add(x);
            return;
        }
        for(int i=0;i<b.length;i++){
            if(!flag[i]){
                flag[i]=true;
                a[u]=b[i];
                dfs(u+1);
                a[u]=0;
                flag[i]=false;
            }
        }
    }
    public static void main(String args[]) throws IOException{
        dfs(0);
        pw.println(set.size());
        pw.close();
    }
}

八、四平方和

蓝桥杯官网_四平方和

 思路:

首先想到暴力枚举四层循环,但时间复杂度为0(n^4),不可取,需要进行优化
考虑空间换时间,定义node类,存储c,d,sum,首先枚举c,d,预处理出c,d, c^2+d^2,存储在链表中,按照sum从小到大排序,然后枚举a,b,同时计算n-a*a-b*b的差值x,二分查找链表,若能够找到sum=x,则此时即a,b,c,d即是答案

代码:

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Main {
    static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter pw=new PrintWriter(System.out);
    public static int nextInt() throws IOException{
        st.nextToken();
        return (int)st.nval;
    }
    static class node implements Comparable<node>{
        int c,d,sum;
        public node(int c,int d,int sum){
            this.c=c;
            this.d=d;
            this.sum=sum;
        }
        public int compareTo(node p){
            return Integer.compare(sum,p.sum);
        }
    }
    static int n;
    static List<node>list=new ArrayList<>();
    public static void main(String args[]) throws IOException{
        n=nextInt();
        int cnt=0;
        for(int c=0;c*c<=n/2;c++){
            for(int d=c;c*c+d*d<=n;d++){
                list.add(new node(c,d,c*c+d*d));
            }
        }
        Collections.sort(list);
        for(int a=0;a*a<=n/4;a++){
            for(int b=a;a*a+b*b<=n/2;b++){
                int x=n-a*a-b*b;
                int l=0,r=list.size()-1;
                while (l<r){
                    int mid=l+r>>1;
                    if(list.get(mid).sum>=x) r=mid;
                    else l=mid+1;
                }
                if(list.get(r).sum==x){
                    int c=list.get(r).c;
                    int d=list.get(r).d;
                    pw.println(a+" "+b+" "+c+" "+d);
                    pw.close();
                    return;
                }
            }
        }
    }
}

九、取球博弈

蓝桥杯官网_取球博弈

 思路:

递归+记忆化搜索
f[num][me][you]共三维状态,num为当前小球的剩余数,me表示此时我手中球的个数是否为奇数,1表示为奇数,0表示为偶数,you同理;

 代码:

import java.io.*;
import java.util.Arrays;

public class Main{
    static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter pw=new PrintWriter(System.out);
    public static int nextInt() throws IOException{
        st.nextToken();
        return (int)st.nval;
    }
    static int n;
    static int N=1010;
    static int f[][][]=new int[N][2][2];
    static int a[]=new int[3];
    public static int dfs(int num,int me,int you){//num为当前剩余球的个数,me:0代表我有偶数个球,1代表我有奇数个球,you同理
        if(f[num][me][you]!=0) return f[num][me][you];
        if(num<a[0]){//最小的都不够拿
            if((me&1) == (you&1)) return 2;//同奇或同偶,平局
            else if((me&1)==1) return 1;//赢
            return -1;//输
        }
        else{
            boolean nowin=false;
            for(int i=2;i>=0;i--){
                if(num<a[i]) continue;
                int res=dfs(num-a[i],you,(me+a[i])&1);//对方结果
                if(res==-1) return f[num][me][you]=1;
                if(res==2) nowin=true;
            }
            if(nowin) return f[num][me][you]=2;//所有情况都无法取胜的前提下,平局;
            return f[num][me][you]=-1;
        }
    }
    public static void main(String args[]) throws IOException{
        for(int i=0;i<3;i++) a[i]=nextInt();
        Arrays.sort(a);
        for(int i=1;i<=5;i++){
            n=nextInt();
            int res=dfs(n,0,0);
            if(res==1) pw.print("+ ");
            else if(res==-1) pw.print("- ");
            else pw.print("0 ");
        }
        pw.close();
    }
}

十、压缩变换

蓝桥杯官网_压缩变换

 思路:

首先考虑暴力做法,用map来记录每个数即其上一次出现的下标t,若当前数之前从未出现过,则将a[i]变为其相反数;否则,从t+1开始到i-1,将每个数都加入到set中,最终set的大小即是两数中间的种类数,将a[i]=set.size(),最终输出a[i]即可;时间复杂度为0(n^2),会超时,在蓝桥杯官网上过了四个测试用例(4/8)
利用树状数组进行优化,时间复杂度0(nlogn),具体详见代码注释

代码一 暴力做法:

import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Main {
    static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter pw=new PrintWriter(System.out);
    public static int nextInt() throws IOException{
        st.nextToken();
        return (int)st.nval;
    }
    static int n;
    static int N=100010;
    static int a[]=new int[N];
    static Map<Integer,Integer>map=new HashMap<>();
    public static void main(String args[]) throws IOException{
        n=nextInt();
        for(int i=1;i<=n;i++) a[i]=nextInt();
        for(int i=1;i<=n;i++){
            int x=a[i];
            if(map.get(x)==null){//之前未出现过
                pw.print(-a[i]+" ");
            }
            else{
                int t=map.get(x);//上次x出现的位置
                Set<Integer> set=new HashSet<>();
                for(int j=t+1;j<i;j++) set.add(a[j]);
                pw.print(set.size()+" ");
            }
            map.put(x,i);
        }
        pw.close();
    }
}

代码二 树状数组优化

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class Main {
    static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter pw=new PrintWriter(System.out);
    public static int nextInt() throws IOException{
        st.nextToken();
        return (int)st.nval;
    }
    static int n;
    static int N=100010;
    static int a[]=new int[N];
    static int tr[]=new int[N];
    static Map<Integer,Integer>map=new HashMap<>();
    public static int lowbit(int x){
        return x&-x;
    }
    public static void add(int x,int v){
        for(int i=x;i<N;i+=lowbit(i)) tr[i]+=v;
    }
    public static int query(int x){
        int res=0;
        for(int i=x;i>=1;i-=lowbit(i)) res+=tr[i];
        return res;
    }
    public static void main(String args[]) throws IOException{
        n=nextInt();
        for(int i=1;i<=n;i++) a[i]=nextInt();
        for(int i=1;i<=n;i++){
            int x=a[i];
            if(map.get(x)==null){//之前未出现过
                a[i]=-a[i];
                add(i,1);
            }
            else{
                int t=map.get(x);//上次出现的位置
                add(t,-1);
                add(i,1);
                a[i]=query(i-1)-query(t);
            }
            map.put(x,i);
        }
        for(int i=1;i<=n;i++) pw.print(a[i]+" ");
        pw.close();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值