历届试题 带分数
问题描述
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
剪枝条件: ac 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;isum/2)
return;
if(total==sum/2)//分割的两个区域和相等,在找包含左上角的分割区可能包含的最小的格子数目
{
int temp=0;
for(int i=0;i=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
历届试题 连号区间数
问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在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;imax) max=a[j];
if(a[j]
历届试题 买不到的数目
问题描述
小明开了一家糖果店。他别出心裁:把水果糖包成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=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 list=new ArrayList<>();
for(int i=1;i<=n;i+=2)
list.add(i);
int index=1;
List temp;//用另一个列表存储需要删除的值
while(index();
int delindex=list.get(index);//获得索引对应的(幸运数),即删除的索引号
//列表下标从0开始,所以i应从索引号-1开始,步长为 幸运数
for(int i=delindex-1;im&&list.get(i)