第四届【蓝桥杯】预赛解题报告

第四届蓝桥杯软件设计大赛已经结束,本以为进不了决赛。

很意外,竟然是java本科B组第一,特意来更新博客。

7月11日到北京参加总决赛。遗憾的是宿舍一同学没有考好,不能并肩作战了。

谢谢某人背后默默的支持,我会继续努力的!!!

<1>.世纪末的星期

2299

算法:直接调用java的API,避免出错。

import java.util.Calendar;
import java.util.Date;
public class EndDay
{
	public static void main(String[] args)
	{
		for(int i=1999;;i+=100)
		{
			Calendar calendar=Calendar.getInstance(); 
			calendar.setTime(new Date(i-1900,11,31));
			if(calendar.get(Calendar.DAY_OF_WEEK)-1==0)
			{
				System.out.println(i);return;
			}
		}
	}
}


<2>.马虎的算式

142

算法:排列检查一下就可以了。

public class MaHu 
{
	static int kinds=0;
	static int a[]=new int[6];
	static boolean vis[]=new boolean[10];
	static void check(int a[])
	{
		int num1=a[1]*10+a[2];
		int num2=a[3]*100+a[4]*10+a[5];
		int num3=a[1]*100+a[4]*10+a[2];
		int num4=a[3]*10+a[5];
		if(num1*num2==num3*num4)kinds++;
	}
	static void dfs(int start,int n)
	{
		if(start==6)
		{
			check(a);
		}
		else
		{
			for(int i=1;i<n;i++)
			{
				if(vis[i]) continue;
				a[start]=i;
				vis[i]=true;
				dfs(start+1,n);
				vis[i]=false;
			}
		}
	}
	public static void main(String[] args)
	{
		dfs(1,10);
		System.out.println(kinds);
	}
}

<3>.振兴中华

35

算法:模拟向右或者向下走7步。

class Node
{
	int x,y;
	public Node(int xx,int yy){x=xx;y=yy;}
}
public class ZhongHua 
{
	static int kinds=0,dir[][]={{0,1},{1,0}};
	static Node aim[]=new Node[8];
	static boolean vis[][]=new boolean[4][5];
	static void dfs(int start,int n)
	{
		if(start==n)	kinds++;
		else
		{
			Node pre=aim[start];
			for(int i=0;i<2;i++)
			{
				int x=pre.x+dir[i][0];
				int y=pre.y+dir[i][1];
				if(x<4 && y<5&& !vis[x][y])
				{
					vis[x][y]=true;
					aim[start+1]=new Node(x,y);
					dfs(start+1,n);
					vis[x][y]=false;
				}
			}
		}
	}
	public static void main(String[] args)
	{
		aim[0]=new Node(0,0);
		dfs(0,7);
		System.out.println(kinds);
	}
}

<4>.黄金连分数

0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375

算法:使用BigDecilmal大数类,由于要求是100位,所以保留200位确保精度在前100位无损失,重复1000次,稳定后再截取前100位进行四舍五入。

public class FenGe 
{
	public static void main(String[] args)
	{
		BigDecimal one,ans;
		ans=one=BigDecimal.ONE;
		for(int i=0;i<1000;i++)
		{
			ans=one.add(ans);
			ans=one.divide(ans, 200, BigDecimal.ROUND_HALF_UP);
			System.out.println(ans);
		}
		System.out.println(ans.setScale(100,BigDecimal.ROUND_HALF_UP));
	}
}

<5>.有理数类

new Rational(ra*x.rb+x.ra*rb, rb*x.rb)

算法:同分母。

<6>.三部排序

p++

算法:0比负数大,认真想一下就明白了。

<7>.错误票据

算法:开个100001的数组hash。同时min,max标记。难点是读取控制台输入数据。

import java.util.Scanner;
public class DuanHao 
{
	static int hash[]=new int [100001];
	public static void main(String[] args)
	{
		Scanner cin=new Scanner(System.in);
		int N=cin.nextInt();
		int min=100001,max=-1;
		int m=0,n=0;
		String strLine=cin.nextLine();//过滤第一次输入n带来的回车换行
		while(N--!=0)
		{
			strLine=cin.nextLine();
			Scanner s=new Scanner(strLine);
			while(s.hasNextInt())
			{
				int t=s.nextInt();     
				min=Math.min(t, min);
				max=Math.max(t, max);
				hash[t]++;
			}
		}
		for(int i=min;i<=max;i++)	
		{
			if(hash[i]==0) m=i;
			if(hash[i]==2) n=i;
		}
		System.out.println(m+" "+n);
	}
}


<8>.幸运数

算法:可以参考筛选素数。打表之后几乎不需要时间。

import java.util.Scanner;
public class XingYun2 
{	
	static int a[]=new int[500000+1];
	static void lucky(int start,int a[],int len)
	{
		int k=start,num=a[start];
		for(int i=k;i<len;i++)	if(i%num!=0) a[k++]=a[i];
		if(num<len)lucky(start+1,a,k);
	}
	public static void main(String[] args)
	{
		int len=500000,kinds=0;
		for(int i=1;i<len;i++) a[i]=2*i-1;
		lucky(2,a,len);
		Scanner cin=new Scanner(System.in);
		int m=cin.nextInt();
		int n=cin.nextInt();
		long sta=System.currentTimeMillis();
		for(int i=1;i<len;i++)
		{
			if(a[i]>=n || a[i]==a[i-1]) break;
			if(a[i]>m && a[i]<n)  kinds++;
		}
		System.out.println(kinds);
//		System.out.println(System.currentTimeMillis()-sta);//时间
	}
}
//1 1000000
//71917
//时间:1ms

 

<9>.带分数

算法:可参考上一篇博客。1000以内150ms内出结果,大于1000大概250ms内运行出结果。带分数

import java.util.Scanner;
public class DaiFenShu
{
	static int kinds=0;
	static int a[]=new int[10];
	static boolean vis[]=new boolean[10];//全排列避免重复
	static int sum(int start,int end)
	{
		int sum=0;
		for(int i=start;i<end;i++) sum=sum*10+a[i+1];
		return sum;
	}
	static void check(int a[],int n,int num)
	{
		int begin=1,temp=num;
		while((temp=temp/10)!=0) begin++;
		for(int k=1;k<begin+1;k++)
		{
			int num1=sum(0,k);
			if(num1>=num) return;//加快跳出
			for(int j=k+(n-k)/2;j<n-1;j++)
			{
				int num2=sum(k,j);
				int num3=sum(j,n-1);
				if(num2>num3 && num2%num3==0 &&num==num1+num2/num3)
				{
//					System.out.println(num+" = "+num1+"+"+num2+"/"+num3);
					kinds++;	
				}
			}
		}	
	}
	static void dfs(int start,int n,int num)
	{
		if(start==n)
		{
			check(a,n,num);
		}
		else
		{
			for(int i=1;i<n;i++)//全排列
			{
				if(vis[i]) continue;
				a[start]=i;
				vis[i]=true;
				dfs(start+1,n,num);
				vis[i]=false;
			}
		}
	}
	public static void main(String[] args)
	{
		Scanner cin=new Scanner(System.in);
		int num=cin.nextInt();
		long start=System.currentTimeMillis();
		dfs(1,10,num);
		long end=System.currentTimeMillis();
//		System.out.println(end-start);//运行时间
		System.out.println(kinds);	
	}
}

 <10>.连号区间数

算法:如一行数据[10, 3,9 ,2 ,7,4,6,5,2, 1], 当索引j=2时,max=10,min=3根据定义:如果一个大的连续区间数包含[1,2]这个区间,那么这个区间长度肯定大于等于10-3+1=8.也就是下次的索引j直接从j+max-min-1即j=8开始,这样就省了很多次的比较max-min是否与j-i相等。特俗情况下,当该行数据是连续的自然数时,算法与双重for效率无任何差异,同样在大数据面前超时。当n=50001时大概在5500ms左右,看来算法应该写到O(n(logn))才能不会超时。如有高效算法,希望能学习下。

下面只是简单的枚举,注定悲剧。

import java.util.Scanner;
public class LianHao 
{
	static int kinds=0;
	static void lianhao(int a[])
	{
		for(int i=1;i<a.length;i++)
		{
			 int min=a[i];
			 int max=a[i];
			for(int j=i;j<a.length;j++)
			{
				min=Math.min(min, a[j]);
				max=Math.max(max, a[j]);
				if(max-min==j-i){kinds++;}
			}
		}
	}
	public static void main(String[] args)
	{
		Scanner cin=new Scanner(System.in);	
		int n=cin.nextInt();
		int a[]=new int[n+1];
		for(int i=1;i<=n;i++) a[i]=cin.nextInt();
		long start=System.currentTimeMillis();
		lianhao(a);
		System.out.println(kinds);
//		System.out.println(System.currentTimeMillis()-start);时间
	}
}

 

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值