LV1

1.穿越时空之门

问题描述

随着 2024 年的钟声回荡,传说中的时空之门再次敞开。这扇门是一条神秘的通道,它连接着二进制和四进制两个不同的数码领域,等待着勇者们的探索。

在二进制的领域里,勇者的力量被转换成了力量数值的二进制表示中各数位之和。

在四进制的领域里,力量的转换规则相似,变成了力量数值的四进制表示中各数位之和。

穿越这扇时空之门的条件是严苛的:当且仅当勇者在二进制领域的力量等同于四进制领域的力量时,他才能够成功地穿越。

国王选定了小蓝作为领路人,带领着力量值从 1 到 2024 的勇者们踏上了这段探索未知的旅程。作为小蓝的助手,你的任务是帮助小蓝计算出,在这 2024 位勇者中,有多少人符合穿越时空之门的条件。

答案提交

这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

题解

常规思路是将所有数字都分别转化为二进制和四进制,然后分别相加,最后比较

将一个数字转化为二进制或四进制的方法,数字除以二或四,得到余数和商,记录余数,商继续做除法得余数,直至商为0,先得到的余数在后,后得到的余数在前,

在这道题里只需要把余数相加即可

更巧妙的做法

二进制转化为四进制,二进制每两位对应四进制的一位

  • 00对应0

  • 01对应1

  • 10对应2

  • 11对应3

这里只有00和01各自相加起来是和四进制中的相等的

2024用二进制表示是11111100100共11位,按照每两位一组共可以有六组,即对应最多六位的四进制

所以是一共六对数字,每一对都有两种可能,00或01,共262^6种可能,最后再去除全为0的情况即可

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static int SumOfBinary(int n)
{
int sum=0;
while(n>0)
{
sum=sum+n%2;
n=n/2;
}
return sum;
}

public static int SumOfQ(int n)
{
int sum=0;
while(n>0)
{
sum=sum+n%4;
n=n/4;
}
return sum;
}

public static void main(String[] args) {
int i=0;
int count=0;
for(i=1;i<=2024;i++)
{
if(SumOfBinary(i)==SumOfQ(i))
{
count++;
}
}
System.out.println(count);
}
}

2.握手问题

问题描述

小蓝组织了一场算法交流会议,总共有 50 人参加了本次会议。在会议上,大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手 (且仅有一次)。但有 7 个人,这 7 人彼此之间没有进行握手 (但这 7 人与除这 7 人以外的所有人进行了握手)。请问这些人之间一共进行了多少次握手?

注意 A 和 B 握手的同时也意味着 B 和 A 握手了,所以算作是一次握手。

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

题解

43个人进行握手,即1累加到42,然后这7个人再分别与43个人握手,即43422\frac{43*42}{2}+7*43

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static void main(String[] args) {
int sum=0,i=0;
for(i=1;i<43;i++) //这里注意不要等于43
{
sum=sum+i;
}
sum=sum+7*43;
System.out.println(sum);
}
}

3.整数变换

问题描述

小蓝有一个整数 n。每分钟,小蓝的数都会发生变化,变为上一分钟的数减去上一分钟的数的各个数位和。

例如,如果小蓝开始时的数为 23,则下一分钟变为 23−(2+3)=18,再下一分钟变为 18−(1+8)=9,再下一分钟变为 9−9=0,共经过了 3 分钟变为 0。

给定一个正整数,请问这个数多少分钟后变为 0。

输入格式

输入一行包含一个整数 n。

输出格式

输出一个整数,表示答案。

样例输入

1
23

样例输出

1
3

题解

直接暴力,但是因为评测用例里用到九次方的数,所以定义的时候要定义为long型的

当n大于0时就减去各个数位和,所以重点在求各个数位和,用循环取模10得到各个位数,再相加,这里要注意要用一个临时变量来记录n,不能让真实的n在计算各个位数和的时候就发生变化。后面再用n减去位数和并且计数器++

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);

long n = scan.nextLong();
int m=0;


while(n>0)
{
long sum=0; //定义在循环里每次大循环都重置一次位数和
long t=n;
while(t>0)
{

sum=sum+t%10;
t=t/10;
}

n=n-sum;
m++;

}
System.out.println(m);


scan.close();
}
}

4.偶串

问题描述

小蓝特别喜欢偶数,当他看到字符串时,他总数要检查一下是不是每种字符都是出现偶数次。给定一个字符串,请帮助小蓝检查一下该字符串是否满足要求。

输入描述

输入一行包含一个字符串,由小写英文字母组成。

输出描述

如果字符串中的每种字符都是出现偶数次,输出大写英文单词 YES ,否则输出大写英文单词 NO。

样例输入

1
banana

样例输出

1
NO

样例输入

1
bbnana

样例输出

1
YES

题解

这道题最简单的做法就是获取每一个字符,然后对应数组中元素大小++,最后判断是否每个数组中的都是偶数

更巧妙的方式是用异或来做,异或用于判断两个数字是否相同,这里是字符会转化为ASCII码,任何数字和0异或都是数字,相同数字异或为0,不同数字异或,最后得到的是不同的数字。只要将第一个数字先和0异或,再一直和后面的数字异或,到最后如果是0就说明全部被抵消了

题目里规定了只能有小写字母,但是用了异或的话,包含了Unicode的字符,而不是只有ASCII中的,处理范围更大

具体异或例子

用abcacb举例

第一步:ans ^= 'a'

ans 初始值为 0
'a' 的 ASCII 值是 97(即 01100001)。

1
2
ans = 0 ^ 97
ans = 97 (二进制:01100001)

第二步:ans ^= 'b'

'b' 的 ASCII 值是 98(即 01100010)。

1
2
ans = 97 ^ 98
ans = 3 (二进制:00000011)

第三步:ans ^= 'c'

'c' 的 ASCII 值是 99(即 01100011)。

1
2
ans = 3 ^ 99
ans = 96 (二进制:01100000)

第四步:ans ^= 'a'

'a' 的 ASCII 值是 97(即 01100001)。

1
2
ans = 96 ^ 97
ans = 1 (二进制:00000001)

第五步:ans ^= 'c'

'c' 的 ASCII 值是 99(即 01100011)。

1
2
ans = 1 ^ 99
ans = 98 (二进制:01100010)

第六步:ans ^= 'b'

'b' 的 ASCII 值是 98(即 01100010)。

1
2
ans = 98 ^ 98
ans = 0 (二进制:00000000)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

/*
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str = scan.nextLine(); //nextLine用来获取整行,如果是next就是获取直到遇到空格等
char[] s = str.toCharArray(); //toCharArray是String的一个方法,用于获取整个字符串存储到一个数组中

int[] a = new int[26]; //这里创建26个字母对应的数字,第一个就代表a出现的次数,以此类推
int n=0,i=0;
for(i=0;i<s.length;i++)
{
a[s[i]-97]++; //这里是ASCII码
}

for(i=0;i<26;i++)
{
if(a[i]%2!=0)
{

System.out.println("NO");
return;
}
}
System.out.println("YES");

scan.close();
}
}
*/

public class Main{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();

int i=0,n=0;
for(i=0;i<s.length();i++)
{
char c = s.charAt(i); //charAt是String的一个方法用于获取一个指定下标的字符
n=n^c; //这里循环做异或
}
if(n==0)
{
System.out.println("YES");
}
else
{
System.out.println("NO");
}
}
}

5.棋盘

问题描述

小蓝拥有 n×n 大小的棋盘,一开始棋盘上全都是白子。小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)。请输出所有操作做完后棋盘上每个棋子的颜色。

输入格式

输入的第一行包含两个整数 n,m,用一个空格分隔,表示棋盘大小与操作数。

接下来 m 行每行包含四个整数 x1x_1y1y_1x2x_2y2y_2,相邻整数之间使用一个空格分隔,表示将在 x1x_1x2x_2 行和 y1y_1y2y_2 列中的棋子颜色取反。

输出格式

输出 n 行,每行 n 个 0 或 1 表示该位置棋子的颜色。如果是白色则输出 0,否则输出 1。

样例输入

1
2
3
4
3 3
1 1 2 2
2 2 3 3
1 1 3 3

样例输出

1
2
3
001
010
100

题解

常规思路直接定义一个二维数组,不用给初值默认为0,然后分别接收数字,再用循环来修改每个棋子,可以用if判断也可以用异或来做

但是数据量过大的时候这种做法会超时

这时候就要考虑差分数组和前缀和

差分数组类似于选择排序,每次都只记录,最后再做实际的交换,差分数组记录变化的起始位置和终点位置,以及变化的值,再用前缀和来记录变化

二维数组的前缀和是上一行加前一列的和再减去交叉重复的左上方元素

最后用前缀和的奇偶来判断变化的次数以及最终状态

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import java.util.Scanner;
/*
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
int i=0,k=0,j=0;
int[][] q = new int[n][n];
for(j=0;j<m;j++)
{
int x1 = scan.nextInt();
int y1 = scan.nextInt();
int x2 = scan.nextInt();
int y2 = scan.nextInt();
for(i=x1-1;i<x2;i++)
{
for(k=y1-1;k<y2;k++)
{
//if(q[i][k]==0)
//{
//q[i][k]=1;
//}
//else
//{
//q[i][k]=0;
//}
/*
q[i][k] ^= 1;
}
}
}
for(i=0;i<n;i++)
{
for(k=0;k<n;k++)
{
System.out.print(q[i][k]);
}
System.out.println();
}
scan.close();
}
}
*/

// 用差分数组和前缀和来做
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();

int arr[][] = new int[n + 2][n + 2];
int result[][] = new int[n + 1][n + 1];

for(j=0;j<m;j++){//记录差分数组头尾
int x1 = sc.nextInt();
int y1 = sc.nextInt();
int x2 = sc.nextInt();
int y2 = sc.nextInt();
arr[x1][y1]++;
arr[x1][y2 + 1]++;
arr[x2 + 1][y1]++;
arr[x2 + 1][y2 + 1]++;
}
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < n + 1; j++) {
//求二维差分数组的前缀和
arr[i][j] += arr[i - 1][j] + arr[i][j - 1] - arr[i - 1][j - 1];
if (arr[i][j] % 2 == 0) {//判断是变1还是变0
result[i][j] = 0;
} else {
result[i][j] = 1;
}
System.out.print(result[i][j]);
}
System.out.println();
}
sc.close();
}
}

6.幸运数字

问题描述

哈沙德数是指在某个固定的进位制当中,可以被各位数字之和整除的正整数。例如 126 是十进制下的一个哈沙德数,因为 (126)10(126)_{10}mod(1+2+6)=0;126 也是八进制下的哈沙德数,因为 (126)10(126)_{10}=(176)8(176)_8,(126)10(126)_{10}mod(1+7+6)=0;同时 126 也是 16 进制下的哈沙德数,因为 (126)10(126)_{10}=(7e)16(7e)_{16}(126)10(126)_{10}mod(7+e)=0。小蓝认为,如果一个整数在二进制、八进制、十进制、十六进制下均为哈沙德数,那么这个数字就是幸运数字,第 1 至第 10 个幸运数字的十进制表示为:1,2,4,6,8,40,48,72,120,126…。现在他想知道第 2023 个幸运数字是多少?你只需要告诉小蓝这个整数的十进制表示即可。

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

题解

和之前的钟声回荡一样可以直接化为对应进制并相加,若能除尽则计数器++,直到2023,可以把计算进制和的函数封装成一个函数

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {

public static int SumOfB(int n)
{
int sum=0;
while(n>0)
{
sum=sum+n%2;
n=n/2;
}
return sum;
}

public static int SumOfO(int n)
{
int sum=0;
while(n>0)
{
sum=sum+n%8;
n=n/8;
}
return sum;
}

public static int SumOfD(int n)
{
int sum=0;
while(n>0)
{
sum=sum+n%10;
n=n/10;
}
return sum;
}

public static int SumOfH(int n)
{
int sum=0;
while(n>0)
{
sum=sum+n%16;
n=n/16;
}
return sum;
}

public static void main(String[] args) {

int n=0,i=1;
while(i>0)
{
if(i%SumOfB(i)==0&&i%SumOfO(i)==0&&i%SumOfD(i)==0&&i%SumOfH(i)==0)
{
n++;
}
if(n==2023)
{
System.out.println(i);
break;
}
i++;
}

}
}

7.判断蓝桥

问题描述

输入一个字符串,请判断这个字符串是否正好是 lanqiao 。在输入时如果只是大小写不同也算作相同。

输入格式

输入一行包含一个字符串。

输出格式

如果是 lanqiao ,输出全小写的字符串 yes ,否则输出全小写的字符串 no

样例输入

1
LanQiao

样例输出

1
yes

样例输入

1
QiaoLan

样例输出

1
no

题解

用忽略大小写的判断相等,或者先变成全部小写,再判断

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);

String str = scan.nextLine();

String ss = "lanqiao";

/*
if(ss.equalsIgnoreCase(str))
{
System.out.println("yes");
}
else
{
System.out.println("no");
}
*/
str=str.toLowerCase();
if(ss.equals(str))
{
System.out.println("yes");
}
else
{
System.out.println("no");
}
scan.close();
}
}

8.星期几

问题描述

给定一天是一周中的哪天,请问 n 天后是一周中的哪天?

输入格式

输入第一行包含一个整数 w,表示给定的天是一周中的哪天,w 为 1 到 6 分别表示周一到周六,w 为 7 表示周日。

第二行包含一个整数 n。

输出格式

输出一行包含一个整数,表示 n 天后是一周中的哪天,1 到 6 分别表示周一到周六,7 表示周日。

样例输入

1
2
6
10

样例输出

1
2

题解

就相加取模7就可以了,注意一下余数为0的时候是星期日

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);

int w = scan.nextInt();
int n = scan.nextInt();

int m =(w+n)%7;
if(m==0)
{
System.out.println(7);
}
else
{
System.out.println(m);
}

scan.close();
}
}

9.英文字母

问题描述

输入一个正整数 nn, 输出第 nn 个大写英文字母。

输入格式

输入一行包含一个正整数 nn

输出格式

输出一行包含一个字母。

样例输入 1

1
12

样例输出 1

1
L

样例输入 2

1
17

样例输出 2

1
Q

题解

获取数字,输出的时候强转,注意字符要用单引号

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);

int s = scan.nextInt();

System.out.println((char)('A'+s-1));

scan.close();
}
}