第一题:
标题:第几天
2000年的1月1日,是那一年的第1天。
那么,2000年的5月4日,是那一年的第几天?
注意:需要提交的是一个整数,不要填写任何多余内容。
答案:125
代码:
package 第九届蓝桥杯;
public class Main01 {
private static int month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
public static void main(String[] args) {
/*
* 2000年的1月1日,是那一年的第1天。 那么,2000年的5月4日,是那一年的第几天?
*/
System.out.println(ok());
}
public static boolean run(int yead) {
if(yead%4==0&&yead%100!=0||yead%400==0) {
return true ;
}
return false;
}
public static int ok() {
int ans = 1;
if(run(2020)) {
month[2] = 29 ;
}
int tx = 1; //月
int ty = 1; //日
while(true) {
ty++;
ans++;
if(ty>month[tx]) {
tx++;
ty = 1;
}
if(tx==5&&ty==4) {
break;
}
}
return ans;
}
}
第二题 :
标题:方格计数
如图p1.png所示,在二维平面上有无数个1x1的小方格
我们以某个小方格的一个顶点为圆心画一个半径为1000的圆。
你能计算出这个圆里有多少个完整的小方格吗?
注意:需要提交的是一个整数,不要填写任何多余内容。
答案: 3137548
代码:
package 第九届蓝桥杯;
public class Main02 {
private static int R = 1000;
private static long ans ;
//第一象限所有方格一个一个查。。。
public static void main(String[] args) {
//枚举第一象限的坐标
for(int i=1;i<=1000;i++) {
for(int j=1;j<=1000;j++) {
if(i*i+j*j<=R*R) {
ans++;
}
}
}
System.out.println(ans*4);
}
}
第三题:
标题:复数幂
设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
求 (2+3i)^123456 等于多少? 即(2+3i)的123456次幂,这个数字很大,要求精确表示。
答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。(2+3i)^2 写成: -5+12i,
(2+3i)^5 的写成: 122-597i
注意:需要提交的是一个很庞大的复数,不要填写任何多余内容。
思路:数据不是一般的大啊,编译器的打印台都打印不出来,我把他打到文件中才看到。
代码:
package 第九届蓝桥杯;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.math.BigInteger;
public class Main03 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream pp=new PrintStream(new FileOutputStream("F:\lao\f.txt"));
System.setOut(pp); //打印重定向 打印到文件中
BigInteger a = new BigInteger("2"); //存实部
BigInteger b = new BigInteger("3");//存虚部
BigInteger c = new BigInteger("2");//存总实部
BigInteger d = new BigInteger("3");//存总虚部
for(int i=1;i<123456;i++) {
BigInteger ta = c;
BigInteger tb = d;
c = a.multiply(ta);
c = c.subtract(b.multiply(tb));
d = b.multiply(ta);
d = d.add(a.multiply(tb));
}
System.out.println(c.toString()+"
---------------------------------------------------------------------------------------------------------- ---"+d.toString());
pp.close();
}
}
第四题:
标题:测试次数
x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。
各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。
x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。
如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。
特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。
如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n
为了减少测试次数,从每个厂家抽样3部手机参加测试。
某次测试的塔高为1000层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?
请填写这个最多测试次数。
注意:需要填写的是一个整数,不要填写任何多余内容。
答案:19
代码:
package 第九届蓝桥杯;
public class Main04 {
private static int n = 3 ;
private static int m = 1000;
private static int[][] dp = new int[n+1][m+1];
public static void main(String[] args) {
//我们假设第一次站在k层楼摔
//dp[i][j]代表有i部手机j层楼时摔坏所有手机的情况下 测试任意抗摔系数的最多次数
//dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k));
//状态转移方程表示 :
//1.不同k之间取最小值
//2.同一 k之间的不同情况取最大值,避免遗漏(如果在这里取了最小值,那么意味着需要更多测试次数情况的测试不到)
//dp[i][j-k]表示还剩下j-k层楼没有测试,在这里不要想当然的认为楼层越高越容易摔碎,我们需要的只是能测试所有的楼层即可
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
dp[i][j] = j; //初始化 最坏的情况莫过于此
}
}
for(int i=2;i<=n;i++) { //一部手机时 我们只能从1层开始一层一层的摔
for(int j=1;j<=m;j++) { //假设一共有 j 层楼
for(int k=1;k<=j;k++) { //假设我们从k层摔
dp[i][j] = Math.min(dp[i][j], Math.max(dp[i-1][k-1],dp[i][j-k] )+1);
}
}
}
System.out.println(dp[3][1000]);
}
}
第五题 :快速排序
蓝桥杯取消代码填空了,这题就不写了。
第六题:
标题:递增三元组
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:
- 1 <= i, j, k <= N
- Ai < Bj < Ck
【输入格式】
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
第四行包含N个整数C1, C2, … CN。
对于30%的数据,1 <= N <= 100
对于60%的数据,1 <= N <= 1000
对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000
【输出格式】
一个整数表示答案
【输入样例】
3
1 1 1
2 2 2
3 3 3
【输出样例】
27
思路:以b数组为基准 二分
代码:
package 第九届蓝桥杯;
import java.util.Arrays;
import java.util.Scanner;
public class Main06 {
private static int n ;
private static long ans;
private static int[] a;
private static int[] b;
private static int[] c;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
a = new int[n];
b = new int[n];
c = new int[n];
for(int i=0;i<n;i++) {
a[i] = sc.nextInt();
}
for(int i=0;i<n;i++) {
b[i] = sc.nextInt();
}
for(int i=0;i<n;i++) {
c[i] = sc.nextInt();
}
Arrays.sort(a);
Arrays.sort(b);
Arrays.sort(c);
for(int i=0;i<b.length;i++) {
ans+=binMin(b[i])*binMax(b[i]);
}
System.out.println(ans);
}
public static long binMax(int x) {
int min = 0;
int max = c.length;
int mid =(min+max)/2;
while(min<max) {
if(c[mid]>x) {
max = mid;
}else if(c[mid]<=x) {
min = mid+1;
}
mid = (min+max)/2;
}
return c.length-max;
}
public static long binMin(int x) { //寻找小于x的最大值
int min = 0;
int max = a.length;
int mid = (max+min)/2;
while(min<max) {
if(a[mid]<x) {
min = mid+1;
}else if(a[mid]>=x) {
max = mid;
}
mid = (max+min)/2;
}
return max;
}
}
第七题
标题:螺旋折线
找规律 ,第九届蓝桥杯b组,之前写过 ,有点麻烦就不写了。。。
第八题
标题:日志统计
小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:
ts id
表示在ts时刻编号id的帖子收到一个"赞"。
现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。
具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。
给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。
【输入格式】
第一行包含三个整数N、D和K。
以下N行每行一条日志,包含两个整数ts和id。
对于50%的数据,1 <= K <= N <= 1000
对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000
【输出格式】
按从小到大的顺序输出热帖id。每个id一行。
【输入样例】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
【输出样例】
1
3
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
思路:双指针
package 第九届蓝桥杯;
import java.util.Arrays;
import java.util.Scanner;
public class Main08 {
//暴力会超时 采用双指针 i 和 j 维护一个不大于d的区间
//时间复杂度 O(nlogn)
private static int n ;
private static int d;
private static int k;
private static megss[] m;
private static int[] count = new int[1000005];;
private static boolean[] flag = new boolean[1000005];;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
d = sc.nextInt();
k = sc.nextInt();
m = new megss[n+1];
for(int i=0;i<n;i++) {
int t = sc.nextInt();
int id=sc.nextInt();
m[i] = new megss(t,id);
}
Arrays.sort(m,0,n);
for(int i=0,j=0;i<n;i++) {
int id = m[i].id;
count[id]++;
while(m[i].t-m[j].t>=d) {
count[m[j].id]--;
j++;
}
if(count[id]>=k) {
flag[id] = true;
}
}
for(int i=0;i<1000001;i++) {
if(flag[i]) {
System.out.println(i);
}
}
}
}
class megss implements Comparable<megss>{
int t ;
int id;
public megss() {
super();
}
public megss(int t, int id) {
super();
this.t = t;
this.id = id;
}
@Override
public int compareTo(megss o) {
// TODO 自动生成的方法存根
return this.t-o.t;
}
}
第九题
标题:全球变暖
你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:
…
.##…
.##…
…##.
…####.
…###.
…
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
…
…
…
…
…#…
…
…
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
【输入格式】
第一行包含一个整数N。 (1 <= N <= 1000)
以下N行N列代表一张海域照片。
照片保证第1行、第1列、第N行、第N列的像素都是海洋。
【输出格式】
一个整数表示答案。
【输入样例】
7
…
.##…
.##…
…##.
…####.
…###.
…
【输出样例】
1
思路:dfs搜一下就好了
代码:
package 第九届蓝桥杯;
import java.util.Arrays;
import java.util.Scanner;
public class Main09 {
private static int n ;
private static int aa ;
private static int bb ;
private static int[] ans;
private static int[][] book ;
private static String[] str ;
private static char[][] ch ;
private static int[][] next = {{0,1},{1,0},{0,-1},{-1,0}};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
str = new String[n];
ch = new char[n][n];
ans = new int[1000005];
book = new int[n][n];
for(int i=0;i<n;i++) {
str[i] = sc.next();
ch[i] =str[i].toCharArray();
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(book[i][j]==0&&ch[i][j]=='#') { //是陆地且未被标记
book[i][j]=++aa;
dfs(i,j,aa);
}
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(ch[i][j]=='#'&&ok(i,j)) {
book[i][j]=0;
}
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(book[i][j]!=-1) {
ans[book[i][j]]++;
}
}
}
for(int i=1;i<ans.length;i++) {
if(ans[i]!=0) {
bb++;
}
}
System.out.println(aa-bb);
}
public static void dfs(int x,int y,int a) {
for(int i=0;i<4;i++) {
int tx = x+next[i][0];
int ty = y+next[i][1];
if(tx>=0&&tx<n&&ty>=0&&ty<n&&ch[tx][ty]=='#'&&book[tx][ty]==0) {
book[tx][ty] = a;
dfs(tx,ty,a);
}
}
}
public static boolean ok(int x,int y) {
for(int i=0;i<4;i++) {
int tx = x+next[i][0];
int ty = y+next[i][1];
if(ch[tx][ty]=='.') {
return true;
}
}
return false;
}
}