前言
本文章只包含题目+答案,没有详细的分析过程(仅为了个人的归纳复盘使用)
题目以及讲解是看B站的视频:https://www.bilibili.com/video/BV1GE411F7Pj?p=253&vd_source=9d88d1508341bdfe8c5c3dccba168d9b
2015-Java省赛第一题——三角形面积
答案:28
关于这题的tips:
热身题,细心
2015-Java省赛第二题——立方变自身
//立方变自身_枚举+检验
public class Main {
static int ans;
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 1; i < 99; i++) {
int i1 = i*i*i;
int sum = sum(i1);
if(sum==i) {
System.out.println(i+" "+i1);
ans++;
}
}
System.out.println(ans);
}
private static int sum(int x) {
String s = String.valueOf(x);
int sum = 0;
for (int i = 0; i < s.length(); i++) {
sum += s.charAt(i)-'0';
}
return sum;
}
}
答案:6
关于这题的tips:
难点在于将立方数的每一位拆开,这里是使用转成字符串方法来实现的
2015-Java省赛第三题——三羊献瑞
//三羊献瑞
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//(abcd+efgb=efcbi)符号化
/*
* a b c d
* + e f g b
* -------------
* e f c b i
*/
//进位:e=1;a=9;f=0;c=b+1;c+g>10
for (int b = 2; b < 9; b++) {
for (int d = 2; d < 9; d++) {
if(b==d) continue;
for (int g = 2; g < 9; g++) {
if(g==b||g==d) continue;
int c = b+1;
if(c==b||c==d||c==g) continue;
if(c+g<10) continue;
int sum = 9000+b*100+c*10+d+1000+g*10+b;
for (int i = 2; i < 9; i++) {
if(i==b||i==d||i==g||i==c) continue;
if(sum == (10000+c*100+b*10+i)){
System.out.print("9"+b+c+d);
System.out.println();
System.out.print("1"+"0"+g+b);
System.out.println();
System.out.print(sum);
}
}
}
}
}
}
}
答案:1085
关于这题的tips:
可以直接用枚举做,但是那样需要做很多次循环和条件判断,所以可以先分析一下可以得出来的数字再进行枚举
2015-Java省赛第四题——循环节长度
//循环节小数
import java.util.Vector;
public class Main {
public static int f(int n,int m) {
n = n % m;
Vector v = new Vector();//Vector等价于列表
for(;;){//死循环
v.add(n);//记录余数
n *= 10;
n = n % m;
if(n==0) return 0;
if(v.indexOf(n)>=0) return v.size()-v.indexOf(n);//填空
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(f(7,18));
}
}
答案:return v.size()-v.indexOf(n)
关于这题的tips:
如果把要填的部分注释掉的话,可以发现程序会运行,但是没有输出,所以我们可以知道横线是要填return值
可以利用debug来理解代码,但是此题有大坑!简单的例子测试不出来异常,但像7/18=0.388888...,如果单纯return v.size()会输出2,但其实循环节长度是1,所以要填return v.size()-v.indexOf(n)
2015-Java省赛第五题——九数组分数
//九数组分数_全排列
public class Main {
private static void test(int[] x) {
int a = x[0]*1000+x[1]*100+x[2]*10+x[3];
int b = x[4]*10000+x[5]*1000+x[6]*100+x[7]*10+x[8];
if(a*3==b) System.out.println(a+" "+b);
}
private static void f(int[] x, int k) {
if(k>=x.length){
test(x);
return;
}
for(int i=k;i<x.length;i++){
int t=x[k]; x[k]=x[i]; x[i]=t;
f(x,k+1);
t=x[k]; x[k]=x[i]; x[i]=t;//填空 回溯
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] x = {1,2,3,4,5,6,7,8,9};
f(x,0);
}
}
答案:t=x[k]; x[k]=x[i]; x[i]=t;
关于这题的tips:
这题如果有看过前两年的真题就应该知道答案是什么了,全排列的回溯过程,无非就是把上面的代码copy下来而已
2015-Java省赛第六题——加法变乘法
//加法变乘法_枚举
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 1; i <= 46; i++) {
for (int j = i+2; j <= 48; j++) {
if(i*(i+1)-(i+i+1)+j*(j+1)-(j+j+1) == 2015-1225){
System.out.println(i+" "+j);
}
}
}
}
}
答案:16
关于这题的tips:
这题可以直接利用等差数列,但是有点繁琐,直接利用差值部分来算就可以了
2015-Java省赛第七题——牌型种数
//牌型种数_递归_模拟
public class Main {
private static int ans;//牌型种数
public static void main(String[] args) {
// TODO Auto-generated method stub
f(0,0);
System.out.println(ans);
}
//k是牌的点数 cnt是手牌数
private static void f(int k, int cnt) {
if(k>13||cnt>13) return;
if(k==13&&cnt==13){
ans++;
return;
}
//每种牌的数量有0,1,2,3,4五种情况
for (int i = 0; i < 5; i++) {
f(k+1,cnt+i);
}
}
}
答案:3598180
关于这题的tips:
分析一下分牌的具体规则,主要还是逻辑方面的问题
2015-Java省赛第八题——饮料换购
import java.util.Scanner;
//饮料换购_模拟
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int ans = 0;
while(n>=3){
n -= 2;
ans += 3;
}
ans += n;
System.out.println(ans);
}
}
关于这题的tips:
分析题意可知,每三个瓶盖可以换一个新的瓶盖,也就是说,每次换的时候,饮料总数都会减去2瓶
每次换的时候,ans+3,最后剩下的饮料数加上ans的数量,就是总的饮料数
2015-Java省赛第九题——垒骰子
import java.util.Scanner;
//垒骰子_递归
public class Main {
static int op[] = new int[7];
static int n;
static int m;
private static final long MOD = 1000000007;//定义一个常量
static void init(){
op[1] = 4;
op[4] = 1;
op[2] = 5;
op[5] = 2;
op[3] = 6;
op[6] = 3;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
init();
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
long conflict[][] = new long[6][6];//6*6的冲突矩阵
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
conflict[i][j] = 1;
}
}
//建立冲突矩阵
for (int i = 0; i < m; i++) {
int a = sc.nextInt();//a和b冲突
int b = sc.nextInt();
conflict[op[a]-1][b-1] = 0;
conflict[op[b]-1][a-1] = 0;
}
//求冲突矩阵的n-1次方
long[][] mPow_n_1 = mPow(conflict,n-1);
//累加矩阵的每个元素
long ans = 0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
ans = (ans + mPow_n_1[i][j])%MOD;
}
}
//ans*4^n
System.out.println(ans*power(4,n)%MOD);
}
private static long power(long i, int n) {
long ans = 1;
while(n!=0){
if((n&1)==1) ans = (ans*i)%MOD;
i = (i*i)%MOD;
n>>=1;
}
return ans;
}
/*矩阵的快速幂*/
private static long[][] mPow(long[][] conflict, int n) {
long[][] e = new long[6][6];
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
if(i==j) e[i][j] = 1;
else e[i][j] = 0;
}
}
while(n!=0){
if((n&1)==1){
e = mMul(e,conflict);
}
conflict = mMul(conflict,conflict);
//n右移一位 除以2
n>>=1;
}
return e;
}
private static long[][] mMul(long[][] a, long[][] b) {
long[][] ans = new long[6][6];
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
for (int k = 0; k < 6; k++) {
ans[i][j] = (ans[i][j]+a[i][k]*b[k][j])%MOD;
}
}
}
return ans;
}
}
关于这题的tips:
这题对我来说很难哈哈,所以我也只是照着敲了一遍,等再次复盘的时候再认真理解一下
2015-Java省赛第十题——生命之树
import java.awt.List;
import java.util.ArrayList;
import java.util.Scanner;
//生命之树_举例分析_模式匹配_递归
public class Main {
static int n;
private static long[] w;
private static java.util.List<Integer>[] g;
private static long ans;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
w = new long[n+1];
//边的邻接表
g = new ArrayList[n+1];
initG();//进行初始化
for (int i = 1; i <= n; i++) {
w[i] = sc.nextLong();
}
for (int i = 0; i < n-1; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
g[a].add(b);
g[b].add(a);
}
dfs(1,0);
System.out.println(ans);
}
/*u作为根所代表的子树有一个最大权和,将其存储在w[u]中
*/
private static void dfs(int u, int fa) {
for (int i = 0; i < g[u].size(); i++) {
Integer child = g[u].get(i);
if(child==fa) continue;
dfs(child,u);
//维护权重
if(w[child]>0)
w[u] += w[child];
}
if(w[u]>ans) ans=w[u];
}
private static void initG() {
for (int i = 0; i < n+1; i++) {
g[i] = new ArrayList<Integer>();
}
}
}
关于这题的tips:
这题也好难,思路看懂了,代码写出来有难度......
总结
程序填空题(填结果)
01:三角形面积 热身 不用编程
02:立方变自身 简单 枚举
03:三羊献瑞 简单枚举 小技巧
程序填空题(填代码)
04:循环节长度 有坑 逻辑
05:九数组分数 全排列 与“带分数”这题相似
程序填空题(填结果)
06:加法变乘法 简单枚举 小技巧
07:牌型种数 递归
编程题
08:饮料换购 模拟
09:垒骰子 递归-动规-矩阵快速幂
10:生命之树Java中递归最多1万层
2015年前8题的题目会比较简单,但是后面两题有一定的难度,只做出来一部分就可以了