1.标题: 猜年龄
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。
一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:
“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。”
请你推算一下,他当时到底有多年轻。
通过浏览器,直接提交他那时的年龄数字。
注意:不要提交解答过程,或其它的说明文字。
18,这题完全不用把0-9这个限制条件敲到代码上,光是4位6位就筛剩几个数了,打印出来观察更快
public class _01_猜年龄1 {
public static void main(String[] args) {
for(int i=11;i<=150;i++) {
int a = i*i*i;
int b = i*i*i*i;
if(a>=1000 && a<=9999 && b>=100000 && b<=999999)
System.out.println(i+" "+a+" "+b);
}
}
}
2.标题: 组素数
素数就是不能再进行等分的数。比如:2 3 5 7 11 等。
9 = 3 * 3 说明它可以3等分,因而不是素数。
我们国家在1949年建国。如果只给你 1 9 4 9 这4个数字卡片,可以随意摆放它们的先后顺序(但卡片不能倒着摆放啊,我们不是在脑筋急转弯!),那么,你能组成多少个4位的素数呢?
比如:1949,4919 都符合要求。
请你提交:能组成的4位素数的个数,不要罗列这些素数!!
注意:不要提交解答过程,或其它的辅助说明文字。
我觉得可以先人工枚举全排,4!/2!=12个吧,比你写个全排函数快一些,而且普通的全排函数面对重复数字不能筛重,得出的是4!,所以人工完了之后就求素数个数吧答案:6 (1499,1949,4919,9419,9491,9941)
public class _02_组素数1 {
public static void main(String[] args) {
int[] a = new int[] {1499,1949,1994,9149,9194,9914,4199,4919,4991,9419,9491,9941};
int ans=0;
for(int i=0;i
也贴一下通过全排列的做法吧,多个步哈希查重
import java.util.HashSet;
import java.util.Set;
//素数判定、素数生成(筛法)、质因数分解
//有重复元素的全排列+检查
public class _02组素数 {
/**
* 处理从k开始的排列
* @param arr
* @param k
*/
static void f(int[] arr, int k) {
if (k == 4)//前面都已确定
check(arr);
for (int i = k; i < 4; i++) {
//交换
int t = arr[k];
arr[k] = arr[i];
arr[i] = t;
f(arr, k + 1);
t = arr[k];
arr[k] = arr[i];
arr[i] = t;
}
}
static Set set = new HashSet();
private static void check(int[] arr) {
int x = arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3];
boolean flag = true;
for (int i = 2; i <= Math.sqrt(x); i++) {
if (x % i == 0) {
flag = false;
System.out.println(x+" false");
break;
}
}
if (flag) {
set.add(x);
System.out.println(x+" true");
}
}
public static void main(String[] args) {
int[] arr = {1, 4, 9, 9};
f(arr, 0);
System.out.println(set.size());
}
}
3.标题: 马虎的算式
小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。
有一次,老师出的题目是: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,暴力到没朋友,填空题暴力枚举就好
import java.util.Scanner;
public class _02_马虎的算式1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int ans=0;
for(int a=1;a<=9;a++)
for(int b=1;b<=9;b++) {
if(b==a)
continue;
for(int c=1;c<=9;c++) {
if(c==a || c==b)
continue;
for(int d=1;d<=9;d++) {
if(d==a || d==b || d==c)
continue;
for(int e=1;e<=9;e++) {
if(e==a || e==b || e==c || e==d)
continue;
if((10*a+b)*(100*c+10*d+e)==(100*a+10*d+b)*(10*c+e))//ab * cde = adb * ce
ans++;
}
}
}
}
System.out.println(ans);
}
}
4.标题: 第39级台阶
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。
要求提交的是一个整数。
注意:不要提交解答过程,或其它的辅助说明文字。
答案:51167078,一定要走偶数步?那不如一次就递归2步把,2步合成一步
public class _04第39级台阶1 {
public static void main(String[] args) {
System.out.println(f(39));
}
static int f(int x) {
if(x==0)
return 1;
if(x<0)
return 0;
return f(x-2)+2*f(x-3)+f(x-4);//左脚1步右脚2步和右脚1步左脚2步不一样的哦
}
}
5.标题:有理数类
有理数就是可以表示为两个整数的比值的数字。一般情况下,我们用近似的小数表示。但有些时候,不允许出现误差,必须用两个整数来表示一个有理数。
这时,我们可以建立一个“有理数类”,下面的代码初步实现了这个目标。为了简明,它只提供了加法和乘法运算。
class Rational
{
private long ra;
private long rb;
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 ________________________________________; //填空位置
}
// 乘法
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;
}
}
使用该类的示例:
Rational a = new Rational(1,3);
Rational b = new Rational(1,6);
Rational c = a.add(b);
System.out.println(a + "+" + b + "=" + c);
请分析代码逻辑,并推测划线处的代码,通过网页提交
注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!!
数学通分:a/b + c/d = (a*d+b*c)/(b*d)
上面的答案都行,不要this是观察到乘法函数也没写
6.标题:逆波兰表达式
正常的表达式称为中缀表达式,运算符在中间,主要是给人阅读的,机器求解并不方便。
例如:3 + 5 * (2 + 6) - 1
而且,常常需要用括号来改变运算次序。
相反,如果使用逆波兰表达式(前缀表达式)表示,上面的算式则表示为:
- + 3 * 5 + 2 6 1
不再需要括号,机器可以用递归的方法很方便地求解。
为了简便,我们假设:
1. 只有 + - * 三种运算符
2. 每个运算数都是一个小于10的非负整数
下面的程序对一个逆波兰表示串进行求值。
其返回值为一个数组:其中第一元素表示求值结果,第二个元素表示它已解析的字符数。
static int[] evaluate(String x)
{
if(x.length()==0) return new int[] {0,0};
char c = x.charAt(0);
if(c>='0' && c<='9') return new int[] {c-'0',1};
int[] v1 = evaluate(x.substring(1));
int[] v2 = __________________________________________; //填空位置
int v = Integer.MAX_VALUE;
if(c=='+') v = v1[0] + v2[0];
if(c=='*') v = v1[0] * v2[0];
if(c=='-') v = v1[0] - v2[0];
return new int[] {v,1+v1[1]+v2[1]};
}
请分析代码逻辑,并推测划线处的代码,通过网页提交。
注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!!
evaluate(x.substring(1+v1[1])),不会就试到会?样例自己弄简单的套
结构应该是这样的:
(操作符占的长度,如果从大的整体看一次长度只能为1)(v1占的长度)(剩下不就是v2占的长度,为v1+1剩下部分)
7.标题:核桃的数量
小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。他的要求是:
1. 各组的核桃数量必须相同
2. 各组内必须能平分核桃(当然是不能打碎的)
3. 尽量提供满足1,2条件的最小数量(节约闹革命嘛)
程序从标准输入读入:
a b c
a,b,c都是正整数,表示每个组正在加班的人数,用空格分开(a,b,c<30)
程序输出:
一个正整数,表示每袋核桃的数量。
例如:
用户输入:
2 4 5
程序输出:
20
再例如:
用户输入:
3 1 1
程序输出:
3
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
题目的意思是求3个数的最小公倍数,了解下简单数论,扩展欧几里得,同余定理,
对于gcd,lcm 都可以通过先写2个数的,在套用2个数的求n个数的,和数学的思想一致,先求出2个数的最小公倍数再求3个数的
import java.util.Scanner;
public class _07核桃的数量1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(lcm(in.nextInt(),in.nextInt(),in.nextInt()));
}
static int gcd(int a,int b) {
if(b==0)
return a;
return gcd(b,a%b);
}
static int gcd(int a,int b,int c) {
return gcd(gcd(a,b),c);
}
static int lcm(int a,int b) {
return a*b/gcd(a,b);
}
static int lcm(int a,int b,int c) {
int s = lcm(a,b);
return s*c/gcd(s,c);
}
}
8.标题:打印十字图
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示(可参见p1.jpg)
$$$$$$$$$$$$$
$ $
$$$ $$$$$$$$$ $$$
$ $ $ $
$ $$$ $$$$$ $$$ $
$ $ $ $ $ $
$ $ $$$ $ $$$ $ $
$ $ $ $ $ $ $
$ $ $ $$$$$ $ $ $
$ $ $ $ $ $ $
$ $ $$$ $ $$$ $ $
$ $ $ $ $ $
$ $$$ $$$$$ $$$ $
$ $ $ $
$$$ $$$$$$$$$ $$$
$ $
$$$$$$$$$$$$$
对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
为了能准确比对空白的数量,程序要求对行中的空白以句点(.)代替。
输入格式:
一个正整数 n (n<30) 表示要求打印图形的层数
输出:
对应包围层数的该标志。
例如:
用户输入:
1
程序应该输出:
..$$$$$..
..$...$..
$$$.$.$$$
$...$...$
$.$$$$$.$
$...$...$
$$$.$.$$$
..$...$..
..$$$$$..
再例如:
用户输入:
3
程序应该输出:
..$$$$$$$$$$$$$..
..$...........$..
$$$.$$$$$$$$$.$$$
$...$.......$...$
$.$$$.$$$$$.$$$.$
$.$...$...$...$.$
$.$.$$$.$.$$$.$.$
$.$.$...$...$.$.$
$.$.$.$$$$$.$.$.$
$.$.$...$...$.$.$
$.$.$$$.$.$$$.$.$
$.$...$...$...$.$
$.$$$.$$$$$.$$$.$
$...$.......$...$
$$$.$$$$$$$$$.$$$
..$...........$..
..$$$$$$$$$$$$$..
请仔细观察样例,尤其要注意句点的数量和输出位置。
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
说实话,看见这种打印的题目就不想做了
import java.util.Scanner;
//2013-C-C第八题一样的
public class _08打印十字图 {
static int N, L = 0, R;
static char[][] arr;
static void deal(int n) {
//n=3,总宽17,最大下标16
int l,r;
l= (N-n)*2;//最小下标
r=l+9+4*(n-1)-1;//最大下标
for (int i = l+2; i <= r-2; i++) {
arr[l][i] = '$';
arr[r][i] = '$';
}
arr[l+1][l+2] = '$';
arr[l+1][r-2] = '$';
arr[r-1][l+2] = '$';
arr[r-1][r-2] = '$';
for (int i = l; i < l+3; i++) {
arr[l+2][i] = '$';
arr[r - 2][i] = '$';
}
for (int i = r; i >r-3 ; i--) {
arr[l+2][i] = '$';
arr[r - 2][i] = '$';
}
for (int i = l+3; i <= r-3; i++) {
arr[i][l] = '$';
arr[i][r] = '$';
}
}
static void printAll() {
for (int i = 0; i <= R; i++) {
for (int j = 0; j <= R; j++) {
if (arr[i][j] != '$') arr[i][j] = '.';
System.out.print(arr[i][j]);
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
R = 9 + 4 * (N - 1) - 1;//最大下标
arr = new char[R+1][R+1];
for (int i = N; i >=1 ; i--) {
deal(i);
}
int c_i=2*N+2;
int c_j=2*N+2;
arr[c_i][c_j]='$';
for (int i = c_i-2; i < c_i+3; i++) {
arr[c_i][i]='$';
}
for (int i = c_i-2; i < c_i+3; i++) {
arr[i][c_j]='$';
}
printAll();
}
}
9.标题:买不到的数目
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入:
两个正整数,表示每种包装中糖的颗数(都不多于1000)
要求输出:
一个正整数,表示最大不能买到的糖数
不需要考虑无解的情况
例如:
用户输入:
4 7
程序应该输出:
17
再例如:
用户输入:
3 5
程序应该输出:
7
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
这题有个数学公式秒杀 a*b-(a+b),正常人想不到可以通过暴力枚举捞点分,甚至AC
public class _09买不到的数目 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
// System.out.println(a*b-a-b);
int max = a * b;
Set ss = new HashSet();
//从0开始枚举到max
for (int x = 0; a * x < max; x++) {
for (int y = 0; a * x + b * y < max; y++) {
ss.add(a * x + b * y);//用不小于0的x和y与系数能组合出来的数加入set中
}
}
for (int i = max - 1; i >= 0; i--) {
if (!ss.contains(i)) { //查找第一个不在set中的值
System.out.println(i);
break;
}
}
}
}
10.标题:剪格子
如图p1.jpg所示,3 x 3 的格子中填写了一些整数。
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
程序输入输出格式要求:
程序先读入两个整数 m n 用空格分割 (m,n<10)
表示表格的宽度和高度
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000
程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目。
例如:
用户输入:
3 3
10 1 52
20 30 1
1 2 3
则程序输出:
3
再例如:
用户输入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
则程序输出:
10
(参见p2.jpg)
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
左边图1,右边图2
思路和普通的dfs搜索+回溯一样,只是这里有个坑,可能会剪成3块,搜出答案的时候,先把和第一个连接的答案存起来,然后用一次dfs求联通块判断,最后别忘了 把求联通块时标记的vis复原,所以考虑到这个就不用boolean数组标记了,改成int,灵活
import java.util.Scanner;
public class _09剪格子 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
m = in.nextInt();
n = in.nextInt();
a = new int[n][m];
vis = new int[n][m];
for(int i=0;isum/2 || t>ans)//稍微剪剪枝
return;
for(int i=0;i<4;i++) {
int j = x + dx[i];
int k = y + dy[i];
if(ok(j,k)) {
vis[j][k] = 1;
dfs(j,k,now+a[j][k],t+1);
vis[j][k] = 0;
}
}
}
static void init() {
for(int i=0;i=0 && x=0 && y=0 && j=0 && k
贴一贴官方的c++代码
//
// Created by zhengwei .
// Copyright © 2019 lanqiao. All rights reserved.
//
/*
标题:剪格子
如图p1.jpg所示,3 x 3 的格子中填写了一些整数。
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
程序输入输出格式要求:
程序先读入两个整数 m n 用空格分割 (m,n<10)
表示表格的宽度和高度
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000
程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目。
例如:
用户输入:
3 3
10 1 52
20 30 1
1 2 3
则程序输出:
3
再例如:
用户输入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
则程序输出:
10
(参见p2.jpg)
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
*/
#include
#include
#include
#include
#define mk(i,j) make_pair(i,j)
using namespace std;
int m, n;
int total;
int g[10][10];
int ans;
/*抽象了一种剪辑方法*/
class Cut {
public:
set > grids;//包含若干格子
int sum;//所有格子的数值的求和
};
/**
* 将st中的元素拷贝到新set中
* @param st
* @return
*/
set > copySet(set > &st) {
set >::iterator iter = st.begin();
set > ans;
while (iter != st.end()) {
// 重新mkpair,加入新set中
ans.insert(*iter);
iter++;
}
return ans;
}
void add(int sum, int i, int j, set > &grids, Cut *&cut_new) {
const pair &pair_n = make_pair(i , j);
// 深度拷贝set
set > grids_copy=copySet(grids);
grids_copy.insert(pair_n);
cut_new->grids=grids_copy;
cut_new->sum=sum+g[i][j];
}
vector vs[100];//分别存储格子数为1~100的各种剪法
int main(int argc, const char *argv[]) {
scanf("%d %d", &m, &n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
scanf("%d", &g[i][j]);
total += g[i][j];
}
}
// 第一个格子就是一半
if (g[0][0] == total / 2) {
printf("%d\n", 1);
return 0;
}
/*左上角格子,只有一种剪法,加入v[1]*/
Cut *c = new Cut();
const pair p = make_pair(0, 0);
c->grids.insert(p);
c->sum = g[0][0];
vs[1].push_back(c);//只包含一个格子且包含00的只有一种剪法
for (int i = 2; i <= m * n; ++i) {
// i是格子数,用vs[i-1]里面的来生成
//迭代vs[i-1]里面的所有剪法
for (int j = 0; j < vs[i - 1].size(); ++j) {
// pCut代表一种剪辑方法
Cut *pCut = vs[i - 1][j];
// 这种剪辑方法里面记录了所有格子,这些格子每个都扩展一个,即形成个数+1的剪法
set > &grids = pCut->grids;
int sum = pCut->sum;
set >::iterator iter = grids.begin();
// 迭代所有的格子,尝试添加它的邻居
while (iter != grids.end()) {
const pair &p = *iter;//代表一个格子的坐标
int x=p.first;
int y=p.second;
if(x+1sum==total/2){
printf("%d\n", i);
return 0;
}else if(cut_new->sum=0&&grids.find(mk(x-1,y))==grids.end()){//上方
Cut *cut_new=new Cut();
add(sum, x-1, y, grids, cut_new);
if(cut_new->sum==total/2){
printf("%d\n", i);
return 0;
}else if(cut_new->sumsum==total/2){
printf("%d\n", i);
return 0;
} else if(cut_new->sum=0&&grids.find(mk(x,y-1))==grids.end()){//左方
Cut *cut_new=new Cut();
add(sum, x, y-1, grids, cut_new);
if(cut_new->sum==total/2){
printf("%d\n", i);
return 0;
}else if(cut_new->sum
小结
01 猜年龄 简单枚举 02 组素数 带重复元素的全排列+素数判定,用到set去重 03 马虎的算式 枚举5个变量,组合后,进行检查 *04 第39级台阶 走楼梯的一个变形,记录走的步数,本质是递归思维 05 有理数类 面向对象和分数加法(通分和约分) *06 逆波兰表达式 递归的整体思维 07 核桃的数量 简单枚举 08 打印十字图 先写死,再变活 **09 买不到的数目 数学 **10 剪格子 深搜+回溯+剪枝 搜索(枚举=迭代和递归,dfs(含回溯和剪枝)、bfs、二分查找) 模拟