1.标题:填算式
请看下面的算式:
(ABCD - EFGH) * XY = 900
每个字母代表一个0~9的数字,不同字母代表不同数字,首位不能为0。
比如,(5012 - 4987) * 36 就是一个解。
请找到另一个解,并提交该解中 ABCD 所代表的整数。
请严格按照格式,通过浏览器提交答案。
注意:只提交 ABCD 所代表的整数,不要写其它附加内容,比如:说明性的文字。
答案:6048,全排
public class _01_填算式 {
public static void main(String[] args) {
dfs(0);
}
static int[] a = new int[] {0,1,2,3,4,5,6,7,8,9};
static void dfs(int m) {
if(m>=10) {
int A = 1000*a[0]+100*a[1]+10*a[2]+a[3];
int B = 1000*a[4]+100*a[5]+10*a[6]+a[7];
int C = 10*a[8]+a[9];
if((A-B)*C==900) {
System.out.println(A+"-"+B+" * "+C+"=="+900);
}
return;
}
for(int i=m;i<10;i++) {
swap(i,m);
dfs(m+1);
swap(i,m);
}
}
static void swap(int i,int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
2.标题:骰子迷题
小明参加了少年宫的一项趣味活动:每个小朋友发给一个空白的骰子(它的6个面是空白的,没有数字),要小朋友自己设计每个面写哪个数字。但有如下要求:
1. 每个面只能填写 0 至 8 中的某一个数字。
2. 不同面可以填写同样的数字,但6个面总和必须等于24。
填好后,小朋友可以用自己填写好数字的骰子向少年宫的两个机器人挑战----玩掷骰子游戏。规则如下:
三方同时掷出自己的骰子,如果出现任何相同的数字,则三方都不计分。
如果三方数字都不同,则最小数字一方扣 1 分,最大数字一方加 1 分。
小明看到了两个机器人手中的骰子分别是:
0 0 0 8 8 8
1 1 4 5 6 7
请你替小明算一下,他如何填写,才能使自己得分的概率最大。
请提交小明应该填写的6个数字,按升序排列,数字间用一个空格分开。
如果认为有多个答案,提交字母序最小的那个方案。
请严格按照格式,通过浏览器提交答案。
注意:只提交一行内容,含有6个被空格分开的数字。不要写其它附加内容,比如:说明性的文字。
3.标题:埃及分数
古埃及曾经创造出灿烂的人类文明,他们的分数表示却很令人不解。古埃及喜欢把一个分数分解为类似: 1/a + 1/b 的格式。
这里,a 和 b 必须是不同的两个整数,分子必须为 1
比如,2/15 一共有 4 种不同的分解法(姑且称为埃及分解法):
1/8 + 1/120
1/9 + 1/45
1/10 + 1/30
1/12 + 1/20
那么, 2/45 一共有多少个不同的埃及分解呢(满足加法交换律的算同种分解)? 请直接提交该整数(千万不要提交详细的分解式!)。
请严格按照要求,通过浏览器提交答案。
注意:只提交分解的种类数,不要写其它附加内容,比如:说明性的文字
答案:7,模拟,枚举的范围大一点比较稳,可以先试1000内,再10000,如果数没变大,基本是稳的
public class _03_埃及分数 {
public static void main(String[] args) {
int ans = 0;
int n = 20000;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if((i+j)/gcd(i+j,i*j)==2 && (i*j)/gcd(i+j,i*j)==45) {
System.out.println("1/"+i+" + "+"1/"+j+" == 2/45");
ans++;
}
System.out.println(ans);
}
static int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
}
4.标题:约数倍数选卡片
闲暇时,福尔摩斯和华生玩一个游戏:
在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
1,2,3, 6,12,18,24 ....
当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
程序则输出必胜的招法!!
例如:
用户输入:
2 3 6
3 6
则程序应该输出:
3
再如:
用户输入:
1 2 2 3 3 4 5
3 4 5
则程序应该输出:
4
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
代码里面有很详细的注释了,博弈,dfs解决 ,思路都是枚举所有对手的情况,如果都不能必胜,那么你就是win
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class _04_约数倍数选卡片 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] s1 = in.nextLine().split(" ");
String[] s2 = in.nextLine().split(" ");
for(int i=0;i<=100;i++)
g[i] = new ArrayList<>();
for(String s:s1)
if(s!="")
num[Integer.parseInt(s)]++;
for(String s:s2)
if(s!="")
choice.add(Integer.parseInt(s));
for(int i=1;i<=100;i++)
if(num[i]>0) {
num[i]--;
for(int j=1;j<=100;j++)
if(num[j]>0 &&(i%j==0 || j%i==0))
g[i].add(j);
num[i]++;
}
int flag = -1;
Collections.sort(choice);//排序,从小到大找答案
for(int x:choice) {
num[x]--;//自己先选一张,再给对手选,对手没得选你win
if(dfs(x)==1) {
flag = x;
break;
}
num[x]++;
}
System.out.println(flag);
}
static int[] num = new int[105];//记录0-100的卡片各有多少
static ArrayList g[] = new ArrayList[105];//预处理,每一个数能选的下一个数,有点像建图
static ArrayList choice = new ArrayList<>();//第一张的可选项
static int dfs(int u) {
for(int i=g[u].size()-1;i>=0;i--) {//果然是逆着遍历才能AC,至于为什么我不知道
int v = g[u].get(i);
if(num[v]>0) {
num[v]--;
int win = dfs(v);//先记录输赢,直接return,回溯会导致失效
num[v]++;
if(win==1)//对方赢了,你还不是输了吗?
return -1;
}
}
return 1;//上面枚举了那么多,对手都没赢,那你就是赢了
}
}
5.标题:网络寻路
X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。
源地址和目标地址可以相同,但中间节点必须不同。
如图1所示的网络。
1 -> 2 -> 3 -> 1 是允许的
1 -> 2 -> 1-> 2 或者 1->2->3->2 都是非法的。
输入数据的第一行为两个整数N M,分别表示节点个数和连接线路的条数(1<=N<=10000; 0<=M<=100000)。
接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
输出一个整数,表示满足要求的路径条数。
例如:
用户输入:
3 3
1 2
2 3
1 3
则程序应该输出:
6
再例如:
用户输入:
4 4
1 2
2 3
3 1
1 4
则程序应该输出:
10
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
dfs+回溯,c++才能在官网AC,要么拿去c语言网A一遍,官网只有c的测试规模 ,这题就是枚举每个点走3步,中途不能回祖先点,这里可以不标记出发点,这样最后可以回到出发点,那么问题来了,如果不标记出发点,第二步可能回到出发点,所以我们要记录它上一个过来的节点,这样第三个点就不会是出发点了,第四点是什么我们不会关心,只要不是标记过的点就行
import java.util.ArrayList;
import java.util.Scanner;
public class 网络寻路 {//c++才能在官网AC
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
g = new ArrayList[n+5];
vis = new boolean[n+5];
for(int i=0;i<=n;i++)
g[i] = new ArrayList<>();
for(int i=1;i<=m;i++) {
int a = in.nextInt();
int b = in.nextInt();
g[a].add(b);
g[b].add(a);
}
for(int i=1;i<=n;i++)
dfs(i,-1,3);//模拟转发2次到再到目的,共走3次
System.out.println(ans);
}
static int n,m,ans=0;
static ArrayList[] g;
static boolean[] vis;
static void dfs(int u,int fa,int step) {
if(step==0) {
ans++;
return;
}
for(int v:g[u])
if(!vis[v] && v!=fa) {
vis[v] = true;
dfs(v,u,step-1);
vis[v] = false;
}
}
}
6.标题:公式求值
输入n, m, k,输出图1所示的公式的值。其中C_n^m是组合数,表示在n个人的集合中选出m个人组成一个集合的方案数。组合数的计算公式如图2所示。
输入的第一行包含一个整数n;第二行包含一个整数m,第三行包含一个整数k。
计算图1所示的公式的值,由于答案非常大,请输出这个值除以999101的余数。
【样例输入1】
3
1
3
【样例输出1】
162
【样例输入2】
20
10
10
【样例输出2】
359316
【数据规模与约定】
对于10%的数据,n≤10,k≤3;
对于20%的数据,n≤20,k≤3;
对于30%的数据,n≤1000,k≤5;
对于40%的数据,n≤10^7,k≤10;
对于60%的数据,n≤10^15,k ≤100;
对于70%的数据,n≤10^100,k≤200;
对于80%的数据,n≤10^500,k ≤500;
对于100%的数据,n在十进制下不超过1000位,即1≤n<10^1000,1≤k≤1000,同时0≤m≤n,k≤n。
【提示】
999101是一个质数;
当n位数比较多时,绝大多数情况下答案都是0,但评测的时候会选取一些答案不是0的数据;
资源约定:
峰值内存消耗(含虚拟机) < 128M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。