6.2020国赛javaC组
https://blog.csdn.net/qq_43449564/article/details/109841937
https://blog.csdn.net/imreal_/article/details/114272929
https://www.dtmao.cc/news_show_375163.shtml
C 扩散
import java.util.LinkedList;
import java.util.Queue;
//定义每一个点,记录坐标和它是经过多少步到达的
class Node{
int x,y,step;
}
public class 扩散 {
//声明n1和n2两个变量
static Node n1,n2;
//记录点是否被访问过
static boolean flag;
static int N = 6200;
static boolean[][] book = new boolean[N][N];
//定义方向,上,下,右,左
static int[][] dirs = {
{-1,0},
{1,0},
{0,1},
{0,-1}
};
//定义队列,offer():压栈,poll():出栈,peek():返回队顶的元素,但不删除
static Queue<Node> queue = new LinkedList<Node>();
//初始就4个点
private static int ans = 4;
public static void main(String[] args) {
//初始化原始的四个点
//而本题是在一个画布上无限的扩散,
//所以是没有边界的,故我们要在二维数组上加上2020即可。
init(2020,2020);
init(4040,2031);
init(2031,2034);
init(4020,4020);
//开始广搜
bfs();
System.out.println(ans);
}
private static void bfs() {
//队列中的元素不为空
while (!queue.isEmpty()) {
//取出并删掉队列头元素,以这个点的视角进行判断
n1 = queue.poll();
//如果取出的点已经是第2020分钟后的,直接结束广搜
if (n1.step == 2020) {
break;
}
//进行四个方向的选择
for (int i = 0; i < 4; i++) {
//新建节点
n2 = new Node();
n2.x =n1.x+dirs[i][0];
n2.y =n1.y+dirs[i][1];
//在当前节点的步骤上+1步,第2020分钟后,叫变成+2020
//这代表了n2的step值是2020
n2.step = n1.step+1;
//这个点没被访问过,而且还没有到第2020步
if (n2.step <=2020 &&!book[n2.x][n2.y] ) {
// System.out.println(n2.x+":"+n2.y);
//标记这个点被访问过了
book[n2.x][n2.y] = true;
ans++;
queue.offer(n2);
}
}
}
}
private static void init(int x, int y) {
book[x][y] = true;
n1 = new Node();
n1.x = x;
n1.y = y;
n1.step = 0;
queue.offer(n1);
}
}
D阶乘约数
- 本题考查约数个数定理
import java.math.BigInteger;
public class 阶乘约数 {
public static void main(String[] args) {
BigInteger num = BigInteger.ONE;
//算出100阶乘的值
for (int i = 1; i <= 5; i++)
num = num.multiply(new BigInteger(String.valueOf(i)));
long res = 1;
//从2开始,知道i*I>num为止
for (BigInteger i = new BigInteger("2"); i.multiply(i).compareTo(num) <= 0; i = i.add(BigInteger.ONE)) {
long cnt = 1;
//约数个数定理
//num%i == 0,是约数,然后执行while语句
/*
例题:正整数378000共有多少个正约数?
解:将378000分解质因数378000=2^4×3^3×5^3×7^1
由约数个数定理可知378000共有正约数(4+1)×(3+1)×(3+1)×(1+1)=160个。
*/
while (num.mod(i).compareTo(BigInteger.ZERO) == 0) {
num = num.divide(i);
cnt++;
}
if (cnt > 1)
res *= cnt;
}
if (num.compareTo(BigInteger.ONE) > 0) res <<= 1;
System.out.println(res);
}
}
E: 本质上升序列
https://blog.csdn.net/m0_51955470/article/details/115706911
https://blog.csdn.net/qq_44443766/article/details/111601650
https://blog.csdn.net/u013098139/article/details/117150847
设str为题目中的目标字符串,定义dp[i]为以str[i]为结尾时的递增子序列的个数。
考虑j<i,遍历j=0~i-1,则有如下讨论:
str[j] < str[i],此时dp[i]=dp[i]+dp[j]
str[j] = str[i],此时dp[i]=dp[i]-dp[j]
str[j] > str[i],此时是降序,不考虑
为了观察方便,就以数字2、1、3、8、5、7、4、5为例:
package 国赛2020C组;
public class 本质上升子序列 {
public static void main(String[] args) {
//一个动态规划的题目
String string =
"tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";
int result = 0;
long ans = 0;
//声明一个数组,里面的的值全为1
int dp[] = new int[string.length()];
for (int i = 0; i < dp.length; i++) {
dp[i] = 1;
}
//每一个都遍历
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < i; j++) {
if (string.charAt(j) < string.charAt(i)) {
dp[i] = dp[i]+dp[j];
}else if(string.charAt(j) == string.charAt(i)) {
dp[i] = dp[i]-dp[j];
}
}
}
for (int i = 0; i < dp.length; i++) {
ans += dp[i];
}
System.out.println(ans);
}
}
F 天干地支
import java.util.Scanner;
public class 天干地支 {
static String[] tiangan = {"jia","yi","bing","ding","wu","ji","geng","xin","ren","gui"};
static String[] dizhi = {"zi","chou","yin","mao","chen","si","wu","wei","shen","you","xu","hai"};
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
// 以2020为基准算一下偏移量就行
System.out.print(tiangan[(n + 6)% 10]);
System.out.print(dizhi[(n - 4) % 12]);
}
}
G皮亚诺曲线距离
https://www.cnblogs.com/valk3/p/14036850.html
H 蓝肽子序列
https://blog.csdn.net/hrn1216/article/details/51534607
public class 蓝肽子序列 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
char [] s1=scanner.nextLine().toCharArray();
char [] s2=scanner.nextLine().toCharArray();
int len1=s1.length;
int len2=s2.length;
int [][]dp=new int[len1+1][len2+1];
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
// 元素相同时
if(s2[j-1]==s1[i-1])
{
// 这个元素等于左上角的值
dp[i][j]=dp[i-1][j-1];
// 当这个元素为大写的时候,才+1,也就是算一个
if('A'<=s2[j-1]&&s2[j-1]<='Z') dp[i][j]++;
}
// 元素不相同
else
{
// 把上面和左面的最大值赋给
if(dp[i-1][j]>=dp[i][j-1])
dp[i][j]=dp[i-1][j];
else dp[i][j]=dp[i][j-1];
}
}
}
System.out.println(dp[len1][len2]);
}
}
I 画廊
import java.text.DecimalFormat;
import java.util.Scanner;
public class 贪心 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
DecimalFormat fmt = new DecimalFormat("#.00");
// long n = sc.nextLong();
int l = sc.nextInt();
int r = sc.nextInt();
int d = sc.nextInt();
int w = sc.nextInt();
// 左右画廊
int[] la = new int[l];
int[] ra = new int[r];
// 左面赋值
for (int i = 0; i < l; ++i) {
la[i] = sc.nextInt();
}
// 右面赋值
for (int i = 0; i < r; ++i) {
ra[i] = sc.nextInt();
}
// 表示走完了第几个
int li = 0;
int ri = 0;
// 求出中间点
double sx = (double) w / 2;
double sy = 0.0;
// 这是总的距离
double dist = 0;
// 没要找到所有的作品,就一直循环
while (li < l || ri < r) {
// 人到作品的距离
double ld = Double.MAX_VALUE, rd = Double.MAX_VALUE;
// 如果左面的作品没找完
if (li < l) {
// 这里是以左边作为y轴,所以x的方向为01
double x = sx - 0;
// 负负得正
double y = sy - la[li];
ld = Math.sqrt(x * x + y * y);
}
// 右面的作品没找完
if (ri < r) {
// 直接求出-w,然后负负得正
double x = sx - w;
double y = sy - ra[ri];
rd = Math.sqrt(x * x + y * y);
}
// 比较到左面和到右面的距离
if (ld < rd) {
// 到左面近
// 记录距离
dist += ld;
// 跟新y的坐标
sy = la[li];
// x坐标移到左面
sx = 0;
++li;
} else {
// 到右面近
dist += rd;
sy = ra[ri];
//
sx = w;
++ri;
}
}
// 这时已经到了最后一个作品,然后求出到终点的距离
double x = sx - (double) w / 2;
double y = sy - d;
dist += Math.sqrt(x * x + y * y);
System.out.println(fmt.format(dist));
}
}
J 答疑
import java.util.Arrays;
import java.util.Scanner;
/*
3
10000 10000 10000
20000 50000 20000
30000 20000 30000
Output:
*/
public class 答疑 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
// 这里是每个人的数据
Task[] tasks = new Task[n];
// 存贮着发消息的时刻
long[] arr = new long[n];
int s,a,e;
long ans = 0,tem = 0;
for (int i = 0; i < tasks.length; i++) {
s = scanner.nextInt();
a = scanner.nextInt();
e = scanner.nextInt();
tasks[i] = new Task(s, a, e);
}
// 按照排序规则,进行排序
Arrays.sort(tasks);
// 发消息时刻的存贮
for (int i = 0; i < tasks.length; i++) {
tem += tasks[i].sum;
arr[i] = tem- tasks[i].e;
}
// 最终答案的获取
for (int i = 0; i < tasks.length; i++) {
ans += arr[i];
}
//
// for (int i = 0; i < arr.length; i++) {
// System.out.println(arr[i]);
// }
System.out.println(ans);
}
}
class Task implements Comparable<Task>{
int s,a,e,sum;
// 这里的sum是这三个数的和,并以此来进行排序,看一个人的耗时小,就往前
public Task(int s, int a, int e) {
super();
this.s = s;
this.a = a;
this.e = e;
this.sum = this.s+this.a+this.e;
}
@Override
public String toString() {
return "Task [s=" + s + ", a=" + a + ", e=" + e + "]";
}
@Override
public int compareTo(Task o) {
//如果总耗时相同,就比较回答时间的长短
if (this.sum == o.sum )
return this.e - o.e;
return this.sum - o.sum;
}
}
7.2020国赛javaB组
E 玩具蛇
public class 玩具蛇 {
// 默认都是false
static boolean [][] key=new boolean[5][5];
// 四个方向的移动 上,下,左,右
static int [][]move={{-1,0},{1,0},{0,-1},{0,1}};
static int ans=0;
public static void main(String[] args) {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
// 开始点变为ture
key[i][j]=true;
dfs(i,j,1);
key[i][j]=false;
}
}
System.out.println(ans);
}
/**
*
* @param x
* @param y
* @param cur 代表是第走的步数,到了16步,就终止
*/
private static void dfs(int x,int y,int cur)
{
// 终点判断
if(cur==16)
{
ans++;
return;
}
// 朝着四个方向移动 上,下,左,右
for (int i = 0; i < move.length; i++) {
int x2=x+move[i][0];
int y2=y+move[i][1];
/**
要去的点并没有超过临界值,并且没有被访问,那就就说明访问的点是合格的
*/
if(x2>=1&&x2<=4&&y2>=1&&y2<=4&&!key[x2][y2])
{
// 将合格的点标记为访问过的
key[x2][y2]=true;
// 在这个点的基础上,在进行选择
dfs(x2,y2,cur+1);
// 说明这个点应经不是合格的点了,或者说已经到了终点了
// 需要回退,然后换个方向进行
key[x2][y2]=false;
}
}
}
}
I: 补给
https://blog.csdn.net/weixin_45640260/article/details/110252819
J 质数行者
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
/*
5 6 1
3 4 1 1 2 1
*/
public class 质数行者 {
static int n,m,w;
static int r1,c1,h1,r2,c2,h2;
// 存放着质数点
static List<Integer> prime;
static int[][][] dp ;
static long Mood = 1000000007;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
w = scanner.nextInt();
r1 = scanner.nextInt();
c1 = scanner.nextInt();
h1 = scanner.nextInt();
r2 = scanner.nextInt();
c2 = scanner.nextInt();
h2 = scanner.nextInt();
prime = new ArrayList<Integer>();
// 所有dp的值都是-1
dp = new int[n+1][m+1][w+1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
Arrays.fill(dp[i][j], -1);
// 两个陷阱的值为0
dp[r1][c1][h1] = 0;
dp[r2][c2][h2] = 0;
// 访问过的值为1
dp[1][1][1] = 1;
// 得到所有可行的质数
int tem = Math.max(n, m);
tem = Math.max(tem, w);
int j;
for (int i = 2; i <= tem ; i++) {
for ( j = 2; j <= (int)Math.sqrt(i); j++) {
if (i%j == 0) {
break;
}
}
if (j> (int)Math.sqrt(i)) {
prime.add(i);
}
}
// 开始递归,这个点也就是要去的点
System.out.println(dfs(n,m,w));
}
private static long dfs(int x, int y, int z) {
// 这个点被访问或者说是陷阱
if (dp[x][y][z] >= 0) {
return dp[x][y][z] ;
}
long res = 0;
// 对所有质数进行遍历
for (int i = 0; i < prime.size(); i++) {
// if的判断,决定了是否越界
if (x - prime.get(i) > 0) {
// 去下一个点
res = (res+dfs(x-prime.get(i), y, z))%Mood;
}
if (y - prime.get(i) > 0) {
res = (res+dfs(x, y-prime.get(i), z))%Mood;
}
if (z - prime.get(i) > 0) {
res = (res+dfs(x, y, z-prime.get(i)))%Mood;
}
}
// 到了这里,递归已经完成了,这个点将被表记为访问过
System.out.println(dp[x][y][z] = (int) res);
return dp[x][y][z] = (int) res;
}
}