临近比赛了,每日一练做挺多了,该做做真题练练手了,今天先把填空做了,明天补更大题
门牌制作
题目链接:http://oj.ecustacm.cn/problem.php?id=1508
签到题,直接全部遍历,找到有2的统计一下就行
答案:624
package year2020A;
/**
* http://oj.ecustacm.cn/problem.php?id=1508
*
* @author Jia
*
*/
public class exercise1 {
public static void main(String[] args) {
int ans = 0;
for (int i = 1; i <= 2020; i++) {
int j = i;
while (j > 0) {
if (j % 10 == 2) {
ans++;
}
j = j / 10;
}
}
System.out.println(ans);
}
}
既约分数
题目链接:http://oj.ecustacm.cn/problem.php?id=1509
还是一样,直接全部遍历,然后判断分子和分母的最大公约数的值是不是1就行了,注意不要直接用质数去拼,我第一次直接计算出质数去做的,然后才发现8/9也是满足条件的,但是两个都不是质数
答案:2481215
package year2020A;
/**
* http://oj.ecustacm.cn/problem.php?id=1509
*
* @author Jia
*
*/
public class exercise2 {
public static void main(String[] args) {
int ans = 0;
int end = 2021;
for (int i = 1; i < end; i++) {
for (int j = 1; j < end; j++) {
if (gcd(i, j) == 1) {
ans++;
}
}
}
System.out.println(ans);
}
/**
* 求最大公约数
*
* @param i
* @param j
* @return
*/
private static int gcd(int i, int j) {
return i % j == 0 ? j : gcd(j, i % j);
}
}
蛇形填数
题目链接:http://oj.ecustacm.cn/problem.php?id=1510
这个题说实话是找规律做的,刚开始做不出来然后直接手算出来的,在22行那个算式
然后代码的话是在后面自己又找了一会规律找出来,(1,1)在第3个蛇形,(2,2)在第5个蛇形,(3,3)在第7个蛇形,然后这样下去
答案:761
package year2020A;
/**
* http://oj.ecustacm.cn/problem.php?id=1510
*
* @author Jia
*
*/
public class exercise3 {
public static void main(String[] args) {
int ans = 0;
int val = 0;
for (int i = 1; i <= 39; i++) {
for (int j = 1; j <= i; j++) {
val++;
if (i == 39 && j == 20) {
ans = val;
}
}
}
System.out.println(ans);
// System.out.println(19 * 39 + 20);
}
}
七段码
题目链接:http://oj.ecustacm.cn/problem.php?id=1511
呃,这个题看题以为挺简单的,然后向直接动手找来着,后来放弃了hhhh
然后后面的想法是把所有边的连接关系记录下来,然后列出所有可能的选择,再去判断这种选择能不能成立
列出全部的选择的话就是回溯法的子集树了,然后由于每次的大小不一样,所以需要多次dfs找子集树,在达到需要的大小后再去判断是否满足条件(其实也可以一次bfs,在每次进入时候都去判断一下,但是我感觉不太好像,还是直接套模板的写法比较好)
然后对每个边进行如下标号,建立一个矩阵存储边的连接关系,对于给出的一个子集判断是否满足条件时需要看这几个边有几个连接点,比如对于0,1,2,3有3个连接点,自己多列几个例子就会发现,对于n个边来说会至少有n-1个连接点,因此如何判断子集是否满足条件的关系就出来了(这里有一种例外,比如0,1,6,5就有4连接点,不过为所谓),除此之外还要确定每一个边与其他边至少有一个连接,在代码中我用的是set去判断的
答案:80
package year2020A;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
/**
* http://oj.ecustacm.cn/problem.php?id=1511
*
* @author Jia
*
*/
public class exercise4 {
static int[][] link = { { 0, 1, 0, 0, 0, 1, 0 }, { 1, 0, 1, 0, 0, 0, 1 }, { 0, 1, 0, 1, 0, 0, 1 },
{ 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 1, 1 }, { 1, 0, 0, 0, 1, 0, 1 }, { 0, 1, 1, 0, 1, 1, 0 }, };
static int ans = 0;
static int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
static ArrayList<Integer> nums = new ArrayList<>();// 记录组合
public static void main(String[] args) {
for (int size = 1; size <= 7; size++) {
dfs(size, 0);
}
System.out.println(ans);
}
/**
* 回溯法
*
* @param size
* @param index
*/
private static void dfs(int size, int index) {
if (nums.size() == size) {
check();
} else {
for (int i = index; i < link.length; i++) {
nums.add(i);
dfs(size, i + 1);
nums.remove(nums.size() - 1);
}
}
}
/**
* 判断这种选择是否满足条件
*/
private static void check() {
int num = nums.size();
Set<Integer> set = new HashSet<>();// 使用hashset是为了确保所有的边都和其他有相连
for (int i = 0; i < nums.size() - 1; i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (link[nums.get(i)][nums.get(j)] == 1) {
num--;
set.add(i);
set.add(j);
}
}
}
// 节点剩余连接数小于1并且所有的边都相连着
if (num <= 1 && (set.size() == nums.size() || nums.size() == 1)) {
ans++;
}
}
}
平面分割
题目链接:http://oj.ecustacm.cn/problem.php?id=1512
这个题也是一个找规律的题,我最后找出来的规律如下:
- 对于圆来说,和其他圆有n个交点,就可以额外把平面分出n个部分
- 对于直线来说,和其他图形有n个交点,就可以额外把平面分出n+1个部分
可能直接看很难看懂,建议先自己手推找一下规律然后过来看
那么我们肯定是让圆和直线有更多的交点就可以了
- 我们首先先计算圆,第一个圆直接将平面分为两个部分,第i个圆可以和前面的圆有(i-1) * 2个交点,也就是可以额外分出(i-1) * 2个区域
- 再计算直线的,第一个直线最多与圆有40个交点,可以额外分出40个区域,第i条直线可以和圆以及直线有 40 + ( i − 1 ) 40+(i-1) 40+(i−1)个交点。也就是可以额外分出 40 + ( i − 1 ) + 1 40+(i-1)+1 40+(i−1)+1个区域
答案:1391
package year2020A;
/**
* http://oj.ecustacm.cn/problem.php?id=1512
*
* @author Jia
*
*/
public class exercise5 {
public static void main(String[] args) {
// 算所有圆可以分成的平面数
int ans = 2;
for (int i = 2; i <= 20; i++) {
ans += (i - 1) * 2;
}
// 算所有边可以分的平面数
ans += 40;
for (int i = 2; i <= 20; i++) {
ans += (i - 1) + 40 + 1;
}
System.out.println(ans);
}
}