第七届蓝桥杯省赛(Java B)

1.煤球数目
有一堆煤球,堆成三角棱锥形。具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形), …
如果一共有100层,共有多少个煤球?
请填表示煤球总数目的数字。 注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

  思路:
  层数        	1 2 3 4  层
	放			1 3 6 10 个
每层相差     	2 3 4 5  个 
public class A {
	public static void main(String[] args) {
		int[] a = new int[101];
		a[1] = 1;
		int sum = 0;
		int ret = 2;
		for (int i = 2; i <= 100; ++i) {
			a[i] = a[i - 1] + ret;
			ret++;
		}
		for (int i = 1; i <= 100; ++i) {
			sum += a[i];
		}
		System.out.println(sum);//171700
	}
}

2.生日蜡烛
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:假设他能活200岁…两重for循环

public class B {
	public static void main(String[] args) {
		for (int i = 1; i <= 200; ++i) {
			int sum = 0;
			for (int j = i; j <= 200; ++j) {
				sum += j;
				if (sum == 236) {
					System.out.println(i);
				}
			}
		}
	}
}

3.凑算式
(参见【图.jpg】)
这个算式中A-I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
在这里插入图片描述

思路:很容易想到全排列,当然多重for循环也可以…全排列的话只要对每次排列得到的结果进行判断,满足凑算式,方案数就加一

//除法运算注意转成double类型。。
public class C {
	static int sum = 0;

	public static void fun(int[] a, int k) {
		if (k == 9) {
			test(a);
			return;
		}
		for (int i = k; i < 9; ++i) {
			{
				int t = a[k];
				a[k] = a[i];
				a[i] = t;
			}
			fun(a, k + 1);
			{
				int t = a[k];
				a[k] = a[i];
				a[i] = t;
			}
		}
	}

	public static void test(int[] a) {
		double ans = a[0] + ((double) a[1] / a[2])
				+ (double) (a[3] * 100 + a[4] * 10 + a[5]) / (a[6] * 100 + a[7] * 10 + a[8]);
		if (ans == 10) {
			sum++;
		}
	}

	public static void main(String[] args) {
		int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
		fun(a, 0);
		System.out.println(sum);
	}
}

4.分小组
9名运动员参加比赛,需要分3组进行预赛。
有哪些分组的方案呢?
我们标记运动员为 A,B,C,… I
下面的程序列出了所有的分组方法。
该程序的正常输出为:
ABC DEF GHI
ABC DEG FHI
ABC DEH FGI
ABC DEI FGH
ABC DFG EHI
ABC DFH EGI
ABC DFI EGH
ABC DGH EFI
ABC DGI EFH
ABC DHI EFG
ABC EFG DHI
ABC EFH DGI
ABC EFI DGH
ABC EGH DFI
ABC EGI DFH
ABC EHI DFG
ABC FGH DEI
ABC FGI DEH
ABC FHI DEG
ABC GHI DEF
ABD CEF GHI
ABD CEG FHI
ABD CEH FGI
ABD CEI FGH
ABD CFG EHI
ABD CFH EGI
ABD CFI EGH
ABD CGH EFI
ABD CGI EFH
ABD CHI EFG
ABD EFG CHI
… (以下省略,总共560行)。

public class D {
    public static String remain(int[] a) {
        String s = "";
        for (int i = 0; i < a.length; i++) {
            if (a[i] == 0)
                s += (char) (i + 'A');
        }
        return s;
    }

    public static void f(String s, int[] a) {
        for (int i = 0; i < a.length; i++) {
            if (a[i] == 1)
                continue;
            a[i] = 1;
            for (int j = i + 1; j < a.length; j++) {
                if (a[j] == 1)
                    continue;
                a[j] = 1;
                for (int k = j + 1; k < a.length; k++) {
                    if (a[k] == 1)
                        continue;
                    a[k] = 1;
                    System.out.println(
                            s + " " + (char) (i + 'A') + (char) (j + 'A') + (char) (k + 'A') + " " + remain(a)); 
                            //填空
                    a[k] = 0;
                }
                a[j] = 0;
            }
            a[i] = 0;
        }
    }

    public static void main(String[] args) {
        int[] a = new int[9];
        a[0] = 1;

        for (int b = 1; b < a.length; b++) {
            a[b] = 1;
            for (int c = b + 1; c < a.length; c++) {
                a[c] = 1;
                String s = "A" + (char) (b + 'A') + (char) (c + 'A');
                f(s, a);
                a[c] = 0;
            }
            a[b] = 0;
        }
    }
}

5.抽签
X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。

那么最终派往W星的观察团会有多少种国别的不同组合呢?
下面的程序解决了这个问题。
数组a[] 中既是每个国家可以派出的最多的名额。
程序执行结果为:
DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF

(以下省略,总共101行)

思路:看代码的话,由f函数的k==a.length我们可以知道这是递归出口,所以可以确定填空位置是再调用f函数本身,其中n-i是减去每次确定了的人数

public class E {

	public static void f(int[] a, int k, int n, String s) {
		if (k == a.length) {
			if (n == 0)
				System.out.println(s);
			return;
		}

		String s2 = s;
		for (int i = 0; i <= a[k]; i++) {
			f(a, k + 1, n - i, s2);//填空
			s2 += (char) (k + 'A');
		}
	}

	public static void main(String[] args) {
		int[] a = { 4, 2, 2, 1, 1, 3 };

		f(a, 0, 5, "");
	}
}

6.方格填数
如下的10个格子
在这里插入图片描述
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:也是个全排列的题,连续的两个数组都不相邻,所以左右上下对角的两个数字之差的绝对值大于1才满足题意。

public class F {
	static long sum = 0;
	public static void fun(int a[], int n) {
		if (n == 10) {
			test(a);
			return;
		} else {
			for (int i = n; i < 10; i++) {
				int temp = a[i];
				a[i] = a[n];
				a[n] = temp;
				fun(a, n + 1);
				int tamp = a[i];
				a[i] = a[n];
				a[n] = tamp;
			}
		}
	}

	public static void test(int[] a) {
		if (Math.abs(a[0] - a[1]) > 1 && Math.abs(a[0] - a[3]) > 1 && Math.abs(a[0] - a[4]) > 1
				&& Math.abs(a[0] - a[5]) > 1 && Math.abs(a[1] - a[2]) > 1 && Math.abs(a[1] - a[4]) > 1
				&& Math.abs(a[1] - a[5]) > 1 && Math.abs(a[1] - a[6]) > 1 && Math.abs(a[2] - a[5]) > 1
				&& Math.abs(a[2] - a[6]) > 1 && Math.abs(a[3] - a[4]) > 1 && Math.abs(a[3] - a[7]) > 1
				&& Math.abs(a[3] - a[8]) > 1 && Math.abs(a[4] - a[5]) > 1 && Math.abs(a[4] - a[7]) > 1
				&& Math.abs(a[4] - a[8]) > 1 && Math.abs(a[4] - a[9]) > 1 && Math.abs(a[5] - a[6]) > 1
				&& Math.abs(a[5] - a[8]) > 1 && Math.abs(a[5] - a[9]) > 1 && Math.abs(a[6] - a[9]) > 1
				&& Math.abs(a[7] - a[8]) > 1 && Math.abs(a[8] - a[9]) > 1) {
			sum++;
		}
	}

	public static void main(String[] args) {
		int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
		fun(a, 0);
		System.out.println(sum);//1580
	}
}

7.剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

思路:这题最一开始的时候想简单了,以为就直接dfs找到5块相邻的就可以了,后来看了大佬的博客说当剪的邮票为“T”字形或者“十”的时候,dfs是走不了的,所以应该先全排列之后再用dfs判断连通块。
//还有一点就是这个全排列和之前的全排列不同,c++里面是直接可以用nextPermutation函数,这个函数是不包含重复元素的,所以java的话需要手动实现这个函数。

import java.util.Arrays;
public class G {
	static int ans = 0;

		public static boolean nextPermutation(int[] arr) {
		if (arr.length <= 1)
			return false;
		int len1 = arr.length - 2;
		for (int i = arr.length - 2; i >= 0 && arr[i] >= arr[i + 1]; i--) {
			len1--;
		}
		if (len1 == -1) 
			return false;
		int len2 = len1 + 1;
		for (int j = len1 + 1; j < arr.length && arr[j] > arr[len1]; j++) {
			len2++;
		}
		swap(arr, len1, len2 - 1);
		Arrays.sort(arr, len1 + 1, arr.length);
		return true;
	}

	public static void swap(int[] arr, int x, int y) {
		int t = arr[x];
		arr[x] = arr[y];
		arr[y] = t;
	}

	public static void dfs(int[][] mp, int x, int y) {
		if (x < 0 || x >= 3 || y < 0 || y >= 4 || mp[x][y] == 0) {
			return;
		}
		mp[x][y] = 0;
		dfs(mp, x + 1, y);
		dfs(mp, x - 1, y);
		dfs(mp, x, y + 1);
		dfs(mp, x, y - 1);
	}

	public static boolean test(int[] a) {
		int[][] mp = new int[3][4];
		int ret = 0;
		for (int i = 0; i < 3; ++i) {
			for (int j = 0; j < 4; ++j) {
				mp[i][j] = a[ret++];
			}
		}
		int sum = 0;
		for (int i = 0; i < 3; ++i) {
			for (int j = 0; j < 4; ++j) {
				if (mp[i][j] == 1) {
					dfs(mp, i, j);
					sum++;
				}
			}
		}
		return sum == 1;// 如果sum不等于1的话说明这个二维数组的邮票是分散的,等于一说明是符合题意的
	}

	public static void main(String[] args) {
		int[] a = { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };
		do {
			if (test(a)) {
				ans++;
			}
		} while (nextPermutation(a));
		System.out.println(ans);//116
	}
}

8.四平方和
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开
例如,输入:
5
则程序应该输出:
0 0 1 2
再例如,输入:
12
则程序应该输出:
0 2 2 2
再例如,输入:
773535
则程序应该输出:
1 1 267 838

思路:三重for循环a、b、c,d可以优化成n-abc;

import java.util.Scanner;

public class H {
	public static void main(String[] args) {
		Scanner cin = new Scanner(System.in);
		int n = cin.nextInt();
		for (int a = 0; a * a <= n; ++a) {
			for (int b = 0; a * a + b * b <= n; ++b) {
				for (int c = 0; a * a + b * b + c * c <= n; ++c) {
					int d = (int) Math.sqrt(n - a * a - b * b - c * c);
					if (a * a + b * b + c * c + d * d == n) {
						System.out.println(a + " " + b + " " + c + " " + d);
						return;
					}
				}
			}
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值