蓝桥杯练习系统历届试题

历届试题 带分数

问题描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
从标准输入读入一个正整数N (N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6

代码

import java.util.*;
/*
深度搜索,1-9构成全排列,整数部分、分子和分母共同分割整个排列。
整数部分为a,分子为b,分母为c
剪枝条件: a<N   b%c=0   b>c   N=a+b/c
 */
public class Main {
	public static int N,count=0;
	public static int[] num=new int[10];
	public static boolean flag[]=new boolean[10];
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		N=scan.nextInt();
		scan.close();
		DFS(1);
		System.out.println(count);
	}
	//求子序列的和
	static int sum(int start,int end)
	{
		int sum=0;
		for(int i=start;i<=end;i++)
		{
			sum=sum*10+num[i];
		}
		return sum;
	}
	//判断是否满足剪枝条件
	static void judge()
	{
		for(int i=1;i<10;i++)
		{
			int a=sum(1,i);
			if(a>=N) return;
			for(int j=i+(10-i)/2;j<9;j++)//寻找分子和分母的分割点
			{
				int b=sum(i+1,j);
				int c=sum(j+1,9);
				if(b%c==0&&b>c&&N==a+b/c)
					count++;
			}
		}
	}
	//深度搜索构成1-9序列
	static void DFS(int start)
	{
		if(start==10)//已找到接下来进行条件判断
			judge();
		for(int i=1;i<10;i++)//1-9
		{
			if(flag[i])//该数字已经使用过,则跳过
				continue;
			num[start]=i;
			flag[i]=true;//访问位置true
			DFS(start+1);
			flag[i]=false;//恢复访问位
		}
	}
}

历届试题 剪格子

问题描述 如下图所示,3 x 3 的格子中填写了一些整数。

+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 3|
+--+--+--+

我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。

如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。

如果无法分割,则输出 0。
输入格式
程序先读入两个整数 m n 用空格分割 (m,n<10)。
表示表格的宽度和高度。
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。
输出格式
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
样例输入1
3 3
10 1 52
20 30 1
1 2 3
样例输出1
3
样例输入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
样例输出2
10

代码

import java.util.*;
/*
深度搜索问题
 */
public class Main {
	public static int[][] a;
	public static int[][] dir={{1,0},{-1,0},{0,-1},{0,1}};
	public static int m,n,sum=0,min=Integer.MAX_VALUE;
	public static boolean[][] flag;
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		m=scan.nextInt();
		n=scan.nextInt();
		a=new int[n][m];
		flag=new boolean[n][m];
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
			{
				a[i][j]=scan.nextInt();
				sum+=a[i][j];
			}
		scan.close();
		flag[0][0]=true;
		DFS(0,0,a[0][0]);
		if(min!=Integer.MAX_VALUE)
			System.out.println(min);
		else
			System.out.println(0);
	}
	public static void DFS(int x,int y,int total)
	{
		if(total>sum/2)
			return;
		if(total==sum/2)//分割的两个区域和相等,在找包含左上角的分割区可能包含的最小的格子数目
		{
			int temp=0;
			for(int i=0;i<n;i++)
				for(int j=0;j<m;j++)
				{
					if(flag[i][j]==true)
						temp++;
				}
			if(temp<min)
				min=temp;
			return;
		}	
		//四个方向的判断
		for(int i=0;i<4;i++)
		{
			int newx=x+dir[i][0];
			int newy=y+dir[i][1];
			//如果超出范围或者下一个点已访问过,则跳过
			if(newx<0||newx>=n||newy<0||newy>=m||flag[newx][newy]==true)
				continue;
			flag[newx][newy]=true;//置访问位
			DFS(newx,newy,total+a[newx][newy]);
			flag[newx][newy]=false;//访问位恢复
		}
	}
}

历届试题 翻硬币

问题描述
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:oo*oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:
输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000
输出格式
一个整数,表示最小操作步数。

样例输入1
**********
o****o****
样例输出1
5
样例输入2
*o**o***o***
*o***o**o***
样例输出2
1

代码

import java.util.*;

public class Main {
	static String s1;
	static String s2;
	static int start=0;
	static int count=0;
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		s1=scan.nextLine();
		s2=scan.nextLine();
		A:while(start<s1.length())
		{
			int p1=start;
			while(s1.charAt(p1)==s2.charAt(p1))
			{
				if(p1==s1.length()-1) break A;
				p1++;
			}
			int p2=p1+1;
			while(s1.charAt(p2)==s2.charAt(p2)) p2++;
			count+=p2-p1;
			start=p2+1;
		}
		scan.close();
		System.out.println(count);
	}
}

历届试题 连号区间数

问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。
输出格式
输出一个整数,表示不同连号区间的数目。
样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
	public static void main(String[] args) throws IOException
	{
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int[] a=new int[n];
		for(int i=0;i<n;i++)
			a[i]=scan.nextInt();
		scan.close();
		int count=0;
		for(int i=0;i<n;i++)
		{
			int min=a[i],max=a[i];
			count++;
			for(int j=i+1;j<n;j++)
			{
				if(a[j]>max) max=a[j];
				if(a[j]<min) min=a[j];
				if(max-min==j-i)
					count++;
			}
		}
		System.out.println(count);
	}
}

历届试题 买不到的数目

问题描述
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数,表示每种包装中糖的颗数(都不多于1000)
输出格式
一个正整数,表示最大不能买到的糖数
样例输入1
4 7
样例输出1
17
样例输入2
3 5
样例输出2
7

代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args)
	{
		Scanner scan=new Scanner(System.in);
		int a=scan.nextInt();
		int b=scan.nextInt();
		scan.close();
		int max=a*b;
		int[] vis=new int[max+1];
		for(int i=0;i*a<max;i++)
			for(int j=0;j*b<max-i*a;j++)
			{
				vis[i*a+b*j]=1;
			}
		for(int i=max-1;i>=0;i--)
		{
			if(vis[i]==0)
			{
				System.out.print(i);
				break;
			}
		}	
	}
}

历届试题 幸运数

问题描述
幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。
首先从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

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
/*
将小于等于n的奇数存入list
这里使用了temp列表来存储需要删除的值
(因为如果直接从list中的删除,后面的数都会向前移,对应的索引号会发生变化,原本要删除的索引已发生变化)
 */
public class Main {
	public static void main(String[] args) throws IOException
	{
		Scanner scan=new Scanner(System.in);
		int m=scan.nextInt();
		int n=scan.nextInt();
		scan.close();
		List<Integer> list=new ArrayList<>();
		for(int i=1;i<=n;i+=2)
			list.add(i);
		int index=1;
		List<Integer> temp;//用另一个列表存储需要删除的值
		while(index<list.size())
		{
			temp=new ArrayList<>();
			int delindex=list.get(index);//获得索引对应的(幸运数),即删除的索引号
			//列表下标从0开始,所以i应从索引号-1开始,步长为 幸运数
			for(int i=delindex-1;i<list.size();i+=delindex)
			{
				temp.add(list.get(i));//将需要删除的值存入temp列表中
			}
			list.removeAll(temp);//从list中删除与temp的相同值
			index++;
		}
		int count=0;
		//System.out.println(list.size());
		for(int i=0;i<list.size();i++)
		{
			if(list.get(i)>m&&list.get(i)<n)//符合范围则+1
			{
				//System.out.println(list.get(i));
				count++;
			}
		}
		System.out.println(count);
	}
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值