【蓝桥杯真题】(2013年 Java省赛 B组)

目录

01.世纪末的星期

02.马虎的算式

03.振兴中华

04.黄金连分数

05.有理数类

06.三部排序

07.错误票据

08.幸运数

09.带分数

10.连号区间数


01.世纪末的星期

曾有邪教称1999年12月31日是世界末日。当然该谣言已经不攻自破。

还有人称今后的某个世纪末的12月31日,如果是星期一则会....

有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!!

于是,“谣言制造商”又修改为星期日......

1999年的12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即xx99年)的12月31日正好是星期天(即星期日)?

请回答该年份(只写这个4位整数,不要写12月31等多余信息)

【解题思路】:利用内置对象calendar;结果为2299

【代码】

package lqb2013;
import java.util.Calendar;
public class _世纪末的星期 {public static void main(String[] args) {
 // TODO Auto-generated method stub
 //得到一个Calendar实例
 Calendar calendar=Calendar.getInstance();
 for(int year=1999;year<10000;year+=100) {
  //设置时间年月日,查看相关代码
  calendar.set(Calendar.YEAR, year);
  calendar.set(Calendar.MONTH, 11);
  calendar.set(Calendar.DAY_OF_MONTH, 31);
  if(calendar.get(Calendar.DAY_OF_WEEK)==1) {
   System.out.print(year);
   break;
  }
 }
}
}

02.马虎的算式

小明是个急性子上小学的时候经常把老师写在黑板上的题目抄错了。 有一次老师出的题目是36 x 495 = ? 他却给抄成了396 x 45 = ?

但结果却很戏剧性他的答案竟然是对的 因为 36 * 495 = 396 * 45 = 17820 类似这样的巧合情况可能还有很多比如27 * 594 = 297 * 54

假设 a b c d e 代表1~9不同的5个数字注意是各不相同的数字且不含0

能满足形如ab * cde = adb * ce 这样的算式一共有多少种呢

【解题思路】:利用枚举,暴力搜索;结果为142

【代码】

package lqb2013;
public class _马虎的算式 {
public static void main(String[] args) {
 // TODO Auto-generated method stub
 int ans=0;
 for(int a=1;a<10;a++) {
  for(int b=1;b<10;b++) {
   if(a!=b) for(int c=1;c<10;c++) {
    if(c!=a&&c!=b) for(int d=1;d<10;d++) {
     if(d!=a&& d!=b&& d!=c) for(int e=1;e<10;e++) {
      if(e!=a&& e!=b&& e!=c&& e!=d) {
       if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e)) {
        ans++;
       }
      }
     }
    }
   }
  }
 }
 System.out.println(ans);
}
}

03.振兴中华

小明参加了学校的趣味运动会,其中的一个项目是:跳格子 地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg)

 从我做起振 
 我做起振兴
 做起振兴中
 起振兴中华

比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。

要求跳过的路线刚好构成“从我做起振兴中华”这句话。

请你帮助小明算一算他一共有多少种可能的跳跃路线呢?

答案是一个整数,请通过浏览器直接提交该数字。注意:不要提交解答过程,或其它辅助说明类的内容

【解题思路】:从“从”开始走,每个格子都有向前和向下走两个方向,向前走到尽头为一种方法,向下走到尽头也可以确定一种方法,故可以由此确定边界。结果为35种。

【代码】

package lqb2013;
public class 振兴中华 {
public static void main(String[] args) {
 // TODO Auto-generated method stub
 int i=0,j=0;
 int ans=f(i,j);
 System.out.print(ans);
}

private static int f(int i, int j) {
 // TODO Auto-generated method stub
 if(i==3||j==4) return 1;
 return f(i+1,j)+f(i,j+1);
}
}

04.黄金连分数

黄金分割数0.61803... 是个无理数,这个常数十分重要,在许多工程问题中会出现。有时需要把这个数字求得很精确。 言归正传,我们如何求得黄金分割数的尽可能精确的值呢?有许多方法。 比较简单的一种是用连分数:

                            1
   黄金数 = ---------------------
                                 1
                     1 + -----------------
                                         1
                              1 + -------------
                                           1
                                   1 + ---------
                                          1 + ...

这个连分数计算的“层数”越多,它的值越接近黄金分割数。 请你利用这一特性,求出黄金分割数的足够精确值,要求四舍五入到小数点后100位。

小数点后3位的值为:0.618
小数点后4位的值为:0.6180
小数点后5位的值为:0.61803
小数点后7位的值为:0.6180340
(注意尾部的0,不能忽略)

你的任务是:写出精确到小数点后100位精度的黄金分割值。 注意:尾数的四舍五入! 尾数是0也要保留! 显然答案是一个小数,其小数点后有100位数字,请通过浏览器直接提交该数字。 注意:不要提交解答过程,或其它辅助说明类的内容。

【解决思路】:

1、由于得出的数据存在规律,这题与斐波拉契有关,故求斐波拉契相邻两项的比值,n越多越精确,最后求n/n+1项

2、由于要到第100位,故这里用到BigInteger和BigDecimal这两个API

3、最后对尾数进行四舍五入即可

4、结果为:0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375

【代码】

package lqb2013;
import java.math.BigDecimal;
import java.math.BigInteger;
public class _黄金连分数 {
public static void main(String[] args) {
 // TODO Auto-generated method stub
 BigInteger a=BigInteger.ONE;
 BigInteger b=BigInteger.ONE;
 for(int i=3;i<400;i++) {
  BigInteger t=b;
  b=a.add(b);
  a=t;
 }
 BigDecimal Div=new BigDecimal(a,110).divide(new BigDecimal(b,110),BigDecimal.ROUND_HALF_DOWN);
 System.out.print(Div.toPlainString().substring(0, 103));
}
}

05.有理数类

有理数就是可以表示为两个整数的比值的数字。一般情况下,我们用近似的小数表示。但有些时候, 不允许出现误差,必须用两个整数来表示一个有理数。 这时,我们可以建立一个“有理数类”,下面的代码初步实现了这个目标。为了简明,它只提供了加法和乘法运算。

【解决思路】:面向对象+分数加法(通分与约分)

使用该类的示例:

Rational a = new Rational(1,3);
Rational b = new Rational(1,6);
Rational c = a.add(b);
System.out.println(a + "+" + b + "=" + c);

【代码】:

    private long gcd(long a, long b) {
        if (b == 0)
            return a;
        return gcd(b, a % b);
    }

    public Rational(long a, long b) {
        ra = a;
        rb = b;
        long k = gcd(ra, rb);
        if (k > 1) { // 需要约分
            ra /= k;
            rb /= k;
        }
    }

    // 加法
    public Rational add(Rational x) {
        // return ________________________________________;  //填空位置
        //答案如下:
        return new Rational(ra * x.rb + rb * x.ra, rb * x.rb);
    }

    // 乘法
    public Rational mul(Rational x) {
        return new Rational(ra * x.ra, rb * x.rb);
    }

    public String toString() {
        if (rb == 1)
            return "" + ra;
        return ra + "/" + rb;
    }
}

public static void main(String[] args) {
    Rational a = new Rational(1, 3);
    Rational b = new Rational(1, 6);
    Rational c = a.add(b);
    System.out.println(a + "+" + b + "=" + c);

    Rational a1 = new Rational(1, 3);
    Rational b1 = new Rational(1, 3);
    Rational c1 = a.add(b1);
    System.out.println(a1 + "+" + b1 + "=" + c1);
}
}

06.三部排序

一般的排序有许多经典算法,如快速排序、希尔排序等。

但实际应用时,经常会或多或少有一些特殊的要求。我们没必要套用那些经典算法,可以根据实际情况建立更好的解法。

比如,对一个整型数组中的数字进行分类排序:

使得负数都靠左端,正数都靠右端,0 在中部。注意问题的特点是:负数区域和正数区域内并不要求有序。可以利用这个特点通过 1 次线性扫描就结束战斗!!

以下的程序实现了该目标。

其中 xx 指向待排序的整型数组,len是数组的长度。

请分析代码逻辑,并推测划线处的代码。

【解决思路】:快速排序(三指针区间法)变体、极限思维(考虑到全部都是0的情况)

【代码】:

package lqb2013;

public class _三部排序 {

     static void sort(int[] x)
     {
         int p = 0;
         int left = 0;//最左边
         int right = x.length-1;//最右边
         
         while(p<=right){
          
             if(x[p]<0){
                 int t = x[left];
                 x[left] = x[p];
                 x[p] = t;
                 left++;
                 p++;
             }
             else if(x[p]>0){
                 int t = x[right];
                 x[right] = x[p];
                 x[p] = t;
                 right--;
                                 
             }
             else{
              p++;
             }
         }
         
         show(x);
     }
     
     static void show(int[] x)
     {
         for(int i=0; i<x.length; i++)
         {
             System.out.print(x[i] + ",");
         }
         
         System.out.println();
     }
     
     public static void main(String[] args)
     {
         int[] x = {25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0};
         sort(new int[]{-1,0,1,-2,0,2,-3,0,0,3,-4,-5,4,-6,0,5,6});
         sort(new int[]{-1,0,-1,-2,0,-2,-3,0,0,-3,-4,-5,-4,-6,0,-5,-6});
         sort(new int[]{1,0,1,2,0,2,3,0,0,3,4,5,4,6,0,5,6});
     }
 
}

07.错误票据

某涉密单位下发了某种票据,并要在年终全部收回。

每张票据有唯一的 ID 号。全年所有票据的 ID 号是连续的,但 ID 的开始数码是随机选定的。

因为工作人员疏忽,在录入 ID号的时候发生了一处错误,造成了某个 ID断号,另外一个 ID重号。

你的任务是通过编程,找出断号的 ID和重号的 ID。

假设断号不可能发生在最大和最小号。

输入描述

要求程序首先输入一个整数 N (N<100)表示后面数据行数。

接着读入 N行数据。

每行数据长度不等,是用空格分开的若干个(不大于 100 个)正整数(不大于10^5105)。

输出描述

要求程序输出 1 行,含两个整数 m,n用空格分隔。

其中,m表示断号 ID,n表示重号 ID。

输入输出样例

示例

输入

2
5 6 8 11 9
10 12 9

输出

7 9

【解决思路】:输入比较特殊,排序、迭代(获取断号和重号)、输出

【代码】:

package lqb2013;

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

public class _错误数据 {
public static void main(String[] args) {
 // TODO Auto-generated method stub
    Scanner sc= new Scanner(System.in);
    ArrayList<Integer> list=new ArrayList<Integer>();
    int N=sc.nextInt();
    sc.nextLine();//吃掉后面的换行
    for(int i=0;i<N;i++) {
     String line=sc.nextLine();//读入第n行
     String[] split=line.split(" ");//将每一行的空格去掉
     for(int j=0;j<split.length;j++) {
      list.add(Integer.parseInt(split[j]));
     }
    }
    Collections.sort(list);
    int a=0,b=0;
    for(int i=1;i<list.size();i++) {
     if(list.get(i)-list.get(i-1)==2) {
      a=list.get(i)-1;
     }
     if(list.get(i).equals(list.get(i-1))) {
      //注意有坑,这里比的是对象,不能用==,==比的是地址
      //也可以写成list.get(i)-list.get(i-1)==0
      b=list.get(i);
     }
    }
    System.out.println(a+" "+b);
}
}

08.幸运数

幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。

首先从1开始写出自然数1,2,3,4,5,6,....

1 就是第一个幸运数。

我们从2这个数开始。把所有序号能被2整除的项删除,变为:

1 _ 3 _ 5 _ 7 _ 9 ....

把它们缩紧,重新记序,为:

1 3 5 7 9 .... 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, ...

此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,...)

最后剩下的序列类似:

1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ...

输入格式

输入两个正整数m n, 用空格分开 (m < n < 1000*1000)

输出格式

程序输出 位于m和n之间的幸运数的个数(不包含m和n)。

样例输入1

1 20

样例输出1

5

样例输入2

30 69

样例输出2

8

【解决思路】:模拟筛选过程,枚举计数

【代码】:

package lqb2013;

import java.util.Scanner;

public class _幸运数字 {
public static void main(String[] args) {
 // TODO Auto-generated method stub
 Scanner sc=new Scanner(System.in );
 int m=sc.nextInt();
 int n=sc.nextInt();
 int a[]=new int[n];
 for(int i=0;i<n;i++) {
  a[i]=i*2+1;
 }
 int l=1;//幸运数字
 
 while(true) {
  int p=l+1;//幸运数字的下一个 
 for(int i=l+1;i<n;i++) {
  if((i+1)%a[l]==0) {}
  else {
   a[p]=a[i];
   p++;
  }
 }
 l++;
 if(a[l]>n)break;
 }
 int ans=0;
 for(int i=0;i<n;i++) {
  if(a[i]>=n)break;
  if(a[i]>m) ans++;
 }
 for(int i=0;i<n;i++) {
  System.out.print(a[i]+" ");
 }
 System.out.println();
 System.out.print(ans); 
}
}

09.带分数

100 可以表示为带分数的形式:100 = 3 + 69258 / 714

还可以表示为:100 = 82 + 3546 / 197

注意特征:带分数中,数字 1~9 分别出现且只出现一次(不包含 0 )。

类似这样的带分数,100 有 11 种表示法。

输入描述

从标准输入读入一个正整数 N\ (N<1000 \times 1000)N (N<1000×1000)。

输出描述

程序输出该数字用数码 1~9 不重复不遗漏地组成带分数表示的全部种数。

注意:不要求输出每个表示,只统计有多少表示法!

输入输出样例

示例

输入

100

输出

11

【解决思路】:1-9用递归做全排序,对每一个排列,都枚举+和=的位置,然后进行进行检查

【代码】:

package lqb2013;

import java.util.Scanner;

public class _带分数 {
    static int N;
    static int ans=0;
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  Scanner sc =new Scanner(System.in);
  N=sc.nextInt();
  int arr[]= {1,2,3,4,5,6,7,8,9};
  int k=0;
  f(arr,k);
  System.out.println(ans);}

private static void f(int[] arr, int k) {
 // TODO Auto-generated method stub

 if(k==9) {
}
 for(int i=k;i<arr.length;i++) {
  //确定第k位
  int t=arr[i];
  arr[i]=arr[k];
  arr[k]=t;
  //确定k的下一位
  f(arr,k+1);
  //进行回溯
  t=arr[i];
  arr[i]=arr[k];
  arr[k]=t;
 }
}

private static void check(int[] arr, int n) {
 // TODO Auto-generated method stub
 
 for(int i=1;i<=7;i++) {
  int num1=toInt(arr,0,i);
  if(num1>=n) continue;
  for(int j=1;j<=8-i;j++) {
  int num2=toInt(arr, i,j);
  int num3=toInt(arr, i+j, 9-i-j);
  if(num2%num3==0 && num1+num2/num3==n) {
   ans++;
  }
  }
 }

}

private static int toInt(int[] arr, int pos, int len) {
 // TODO Auto-generated method stub
 int s=1;
 int num=0;
 for(int i=pos+len-1;i>=pos;i--) {
     num+=arr[i]*s;
     s*=10;
 }
 return num;
}
}

10.连号区间数

小明这些天一直在思考这样一个奇怪而有趣的问题:

在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:

如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。

当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。

输入格式

第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。

第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。

输出格式

输出一个整数,表示不同连号区间的数目。

示例:

用户输入:

4
3 2 4 1

程序应输出:

7

用户输入:

5
3 4 2 5 1

程序应输出:

9

解释:

第一个用例中,有7个连号区间分别是:[1,1], [1,2], [1,3], [1,4], [2,2], [3,3], [4,4]

第二个用例中,有9个连号区间分别是:[1,1], [1,2], [1,3], [1,4], [1,5], [2,2], [3,3], [4,4], [5,5]

【解决思路】:枚举所有区间,检查这个区间里面的数排序后是否连号

【代码】:

package lqb2013;
import java.util.Scanner;
public class _连号区间数 {
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+1];
    for(int i=1;i<N+1;i++) {
     arr[i]=sc.nextInt();
    }
    int ans=0;

    for(int i=1;i<N+1;i++) {
        int max=arr[i];
        int min=arr[i];
     for(int j=i;j<N+1;j++) {
      if(arr[j]>max) max=arr[j];
      if(arr[j]<min) min=arr[j];
      if(j==i) {
       ans++;
      }
      else {
      
       if(max-min==j-i) {
        ans++;

       }
      }
      
     }
    }
    System.out.print(ans);
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值