标题:国王的遗产
X国是个小国。国王K有6个儿子。在临终前,K国王立下遗嘱:国王的一批牛作为遗产要分给他的6个儿子。
其中,大儿子分1/4,二儿子1/5,三儿子1/6,....
直到小儿子分1/9。
牛是活的,不能把一头牛切开分。
最后还剩下11头牛,分给管家。
请计算国王这批遗产中一共有多少头牛。
这是一个整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性的文字)
答案:2520
标题:六角幻方
把 1 2 3 ... 19 共19个整数排列成六角形状,如下:
* * *
* * * *
* * * * *
* * * *
* * *
要求每个直线上的数字之和必须相等。共有15条直线哦!
再给点线索吧!我们预先填好了2个数字,第一行的头两个数字是:15 13,参见图【p1.png】,黄色一行为所求。
请你填写出中间一行的5个数字。数字间用空格分开。
这是一行用空格分开的整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性的文字等)
public class Main{
static int[][] ab={{2,6,11},{0,3,7},{7,12,16},{11,15,18},{16,17,18},{3,4,5,6},{7,8,9,10,11},{12,13,14,15},{1,4,8,12},{2,5,9,13,16},{6,10,14,17},{1,5,10,15},{0,4,9,14,18},{3,8,13,17}};
//构建所有的直线
static int[] arr;//arr为当前的图案每个单元数
static boolean[] bo;//bo为记录每个数是否用过
public static void main(String[] args)throws Exception{
// long t1=System.currentTimeMillis();
arr=new int[19];
arr[0]=15;
arr[1]=13;
arr[2]=10;
bo=new boolean[20];
bo[10]=true;
bo[13]=true;
bo[15]=true;
p(0);
long t2=System.currentTimeMillis();
// System.out.println(t2-t1);//2ms
}
public static void p(int pi) {//这个方法是递归每个直线
if(pi==ab.length) {
System.out.println(arr[7]+" "+arr[8]+" "+arr[9]+" "+arr[10]+" "+arr[11]);
// System.out.println(arr[0]+" "+arr[1]+" "+arr[2]);
// System.out.println(arr[3]+" "+arr[4]+" "+arr[5]+" "+arr[6]);
// System.out.println(arr[7]+" "+arr[8]+" "+arr[9]+" "+arr[10]+" "+arr[11]);
// System.out.println(arr[12]+" "+arr[13]+" "+arr[14]+" "+arr[15]);
// System.out.println(arr[16]+" "+arr[17]+" "+arr[18]);
return;
}
pp(pi,0);
}
public static void pp(int pi,int pj) {//这个方法是对每个直线的每个单元进行填数和判断
if(pj==ab[pi].length) {//如果把这一条线填完了,就进行判断,如果可行,那就进行下一条线的判断
int sum=0;
for(int i=0;i
这道题显然是典型的建立公式题目(因为暴力的运转是15!次也就是10^13,相当于运行几千小时,显然不可能得到答案的),建立一个固定公式,对每个直线,用类似做数独的方式进行填数——也就是数独的固定最简方法,从可能性最少的线开始填数,一直到可能性最大的直线——也就是程序中的ab数组顺序。
数独方式的算法不存在超时——因为几乎不存在运行运行时间——这个程序的运行时间是2ms。(暴力居然会超时几千小时?哼哼,看我不把你优化到臭虫级别我就不放过你!)
标题:格子放鸡蛋
X星球的母鸡很聪明。它们把蛋直接下在一个 N * N 的格子中,每个格子只能容纳一枚鸡蛋。它们有个习惯,要求:每行,每列,以及每个斜线上都不能有超过2个鸡蛋。如果要满足这些要求,母鸡最多能下多少蛋呢,有多少种摆放方法呢?
下面的程序解决了这个问题,请仔细分析程序逻辑,推断划线处缺少的代码。
public class A
{
static int max = 0;
static int T = 0;
static final int N = 6;
static void f(int[][] da, int r, int c)
{
if(r>=N){
int n = count(da);
if(n>max) {
max = n;
T = 0;
}
if(n==max) T++;
return;
}
int r_next = r;
int c_next = c + 1;
if(c_next>=N){
c_next = 0;
r_next++;
}
if(____________________){ // 填空位置
da[r][c] = 1;
f(da, r_next, c_next);
}
da[r][c] = 0;
f(da, r_next, c_next);
}
static int count(int[][] da)
{
int n = 0;
for(int i=0; i
return n;
}
static int spy(int[][] da, int r, int c)
{
int m=0;
// 该行
int n=0;
for(int i=0; i
//该列
n=0;
for(int i=0; i
//右斜线
n=0;
for(int i=0; i
if(da[r-i][c-i]==1) n++;
}
for(int i=1; i
if(da[r+i][c+i]==1) n++;
}
if(n>m) m = n;
//左斜线
n=0;
for(int i=0; i
if(da[r-i][c+i]==1) n++;
}
for(int i=1; i
if(da[r+i][c-i]==1) n++;
}
if(n > m) m = n;
return m;
}
public static void main(String[] args)
{
int[][] da = new int[N][N];
f(da, 0, 0);
System.out.println(max);
System.out.println(T);
}
}
注意:通过浏览器提交答案。只填写缺少的内容,不要填写任何多余的内容(例如:说明性文字或已有符号)。
public class Main
{
static int max = 0;
static int T = 0;
static final int N = 6;
static void f(int[][] da, int r, int c)
{
if(r>=N){//如果递归完毕,计算有多少个蛋
int n = count(da);
if(n>max) {//如果有更小的蛋,计数T归零,max更新
max = n;
T = 0;
}
if(n==max) T++;//否则计数加一
return;
}
int r_next = r;
int c_next = c + 1;
if(c_next>=N){//往右走一步,如果走到底了,行数加一,列数归零
c_next = 0;
r_next++;
}
if(r_next>=N?false:spy(da,r_next,c_next)<2){ //如果当前行步数最后一行,那么计算这个地方是否可以放蛋
da[r][c] = 1;
f(da, r_next, c_next);
}
da[r][c] = 0;
f(da, r_next, c_next);
}
static int count(int[][] da)//计算有多少个蛋
{
int n = 0;
for(int i=0; im) m = n;
//该列
n=0;
for(int i=0; im) m = n;
//右斜线
n=0;
for(int i=0; i=N || c+i>=N) break;
if(da[r+i][c+i]==1) n++;
}
if(n>m) m = n;
//左斜线
n=0;
for(int i=0; i=N) break;
if(da[r-i][c+i]==1) n++;
}
for(int i=1; i=N || c-i<0) break;
if(da[r+i][c-i]==1) n++;
}
if(n > m) m = n;
return m;
}
public static void main(String[] args)
{
int[][] da = new int[N][N];
f(da, 0, 0);
System.out.println(max);
System.out.println(T);
}
}
很简单的一个填空题,也就是考察spy的用途而已。
标题:排列序数
如果用a b c d这4个字母组成一个串,有4!=24种,如果把它们排个序,每个串都对应一个序号:
abcd 0
abdc 1
acbd 2
acdb 3
adbc 4
adcb 5
bacd 6
badc 7
bcad 8
bcda 9
bdac 10
bdca 11
cabd 12
cadb 13
cbad 14
cbda 15
cdab 16
cdba 17
...
现在有不多于10个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?
【输入格式】
一行,一个串。
【输出格式】
一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是0。
例如:
输入:
bdca
程序应该输出:
11
再例如:
输入:
cedab
程序应该输出:
70
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
import java.util.Scanner;
public class Main{
static int answ=0;
public static void main(String[] args){
Scanner in=new Scanner(System.in);
char[] arr=in.next().toCharArray();
p(arr,0);
System.out.println(answ);
}
public static void p(char[] arr,int pi) {
if(pi==arr.length)//如果到了最后一位结束循环
return;
int sum=1;
for(int i=1;i
解析:
70=4*3*2*2+3*2*3+2*2+1*0
11=3*2*1+2*2+1*1
标题:幂一矩阵
天才少年的邻居 atm 最近学习了线性代数相关的理论,他对“矩阵”这个概念特别感兴趣。矩阵中有个概念叫做幂零矩阵。对于一个方阵 M ,如果存在一个正整数 k 满足 M^k = 0 ,那么 M 就是一个幂零矩阵。(^ 表示乘方)
atm 不满足幂零矩阵,他自己设想了一个幂一矩阵:对于一个方阵 M ,如果存在一个正整数 k 满足 M^k = I ,其中 I 是单位矩阵,那么 M 就是一个幂一矩阵。
atm 特别钟情于这样一种方阵:每行每列有且仅有一个 1 。经过 atm 不断实验,他发现这种矩阵都是幂一矩阵。
现在,他的问题是,给定一个满足以上条件的方阵,他想求最小的 k 是多少。
【输入格式】
第一行一个正整数 n ,表示矩阵大小是 n * n 。
接下来 n 行,每行两个正整数 i j 表示方阵的第 i 行第 j 列为 1。
1 <= i, j <= n 。
行号,列号都从1开始。
【输出格式】
一行。一个正整数,即题目中所说最小的 k 。
【样例输入】
5
3 1
1 2
4 4
2 3
5 5
【样例输出】
3
【数据范围】
对于 30% 的数据满足 n <= 10
对于 60% 的数据答案不超过 10^18
对于 100% 的数据满足 n <= 10000
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
public class Main{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[] arr=new int[n];
for(int i=0;i
解析:
技巧一:
如:某个矩阵里的某个“1”的位置是 (1,3),当它遇到(乘以)位置为(3,5)这样的(以3开头的坐标的)“1”,“1”的坐标就变成了(1,5),因此当它继续和位置x轴为5的“1”相遇,就会变成坐标为(1,x)的“1”,当x为1的时候,(1,1)的位置就是“1”了——而这个相遇(相乘)次数就是(1,1)变成1需要的最小次幂。 而每当数据的幂是这个最小循环次数的整数倍的时候,(1,1)这个位置就会是“1”。
技巧二:
我们就可以通过求出:每个(x,x)这样的坐标的数字为“1”的时候,就是这个最小的幂,也就是答案了。
因此我们就需要求每个(x,x)坐标变成“1”的时候需要的最小(相遇)相乘次数,把这些所有的次数gcd得到它的最小公倍数,这个最小公倍数就是这道题的答案。
技巧三:
而,在我们求(1,1)这个位置需求的最小相遇次数的时候,我们会遇到
(1,3)—>(3,5)=(1,5)
(1,5)—>(5,7)=(1,7)
(1,7)—>(7,1)=(1,1)
类似于这样的情况,
仔细观察会发现,如果得出1的最小循环次数为3的情况下,那么它相遇过的数5,7的最小循环次数也是3,且它只要相遇了的数字,就处于同一轮回之中,就肯定是相同的循环次数,至于如果实在不理解原因,可以想想如果不是相同的循环次数的情况下,自然就会出现,最终没办法达成单位矩阵了,因为根本没办法消掉这个“1”——于是根据这个情况,我们就可以大大减少重复计算的次数了。
技巧四:题中所说70%答案不会超过10^18,也就是说30%的答案超过了10^18次方,也就是说这些答案,long类型也没办法存储,自然就需要biginteger来进行计算答案了,而biginteger的方法里,查api可得:自带了gcd方法来求最大公约数也就可以求出最小公倍数了,那就是这道题的答案了。
标题:供水设施
X星球的居民点很多。Pear决定修建一个浩大的水利工程,以解决他管辖的N个居民点的供水问题。现在一共有N个水塔,同时也有N个居民点,居民点在北侧从1号到N号自西向东排成一排;水塔在南侧也从1号到N号自西向东排成一排。
N条单向输水线(有水泵动力),将水从南侧的水塔引到北侧对应的居民点。
我们不妨将居民点和水塔都看做平面上的点,居民点坐标为(1,K)~(N,K),水塔为(1,0)~(N,0)。
除了N条纵向输水线以外,还有M条单向的横向输水线,连接(Xi,Yi)和(Xi,(Yi)+1)或者(Xi,Yi)和(Xi,(Yi)-1)。前者被称为向右的水路,而后者是向左的。不会有两条水路重叠,即便它们方向不同。
布局的示意图如:【p1.png】所示。
显然,每个水塔的水都可以到达若干个居民点(而不仅仅是对应的那个)。例如上图中,4号水塔可以到达3、4、5、6四个居民点。
现在Pear决定在此基础上,再修建一条横向单项输水线。为了方便考虑,Pear认为这条水路应当是自左向右的,也就是连接了一个点和它右侧的点(例如上图中连接5和6两个纵线的横向水路)。
Pear的目标是,修建了这条水路之后,能有尽可能多对水塔和居民点之间能到达。换句话说,设修建之后第i个水塔能到达Ai个点,你要最大化A1+A2+...+An。
根据定义,这条路必须和X轴平行,但Y坐标不一定要是整数。注意:虽然输入中没有重叠的水路,但是你的方案可以将新修的输水线路与已有的水路重叠。
【输入数据】
输入第一行包含三个正整数N,M,K,含义如题面所述:N是纵向线数,M横向线数,K是居民点纵坐标。
接下来M行,每行三个整数。前两个正整数Xi Yi表示水路的起点坐标;
1<=Xi<=N,0
保证水路都是合法的,也就是不会流向没有定义的地方。
【输出数据】
输出一行。是一个正整数,即:题目中要求的最大化的A1+A2+...+An。
【输入样例1】
4 3 2
1 1 1
3 1 0
3 1 1
【输出样例1】
11
【输入样例2】
7 9 4
2 3 0
7 2 0
6 3 1
6 1 0
2 1 1
3 3 1
5 2 0
2 2 1
7 1 0
【输出样例2】
21
【数据范围】
对于20%的数据,N,K<=20,M<=100
对于40%的数据,N,K<=100,M<=1000
对于60%的数据,N,K<=1000,M<=100000
对于100%的数据,N,K<=50000,M<=100000
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。