第十三届蓝桥杯大赛软件组省赛 Python大学A组 个人题解
摘要
Title: A, B, C, D, F, G
Powered by:NEFU AB-IN
Python大学A组 个人题解
-
试题 A: 裁纸刀
-
试题 B: 寻找整数
-
思路
中国剩余定理拓展版的板子题,由于模数两两不互质,所以不能用通式
设计到不定方程的最小整数解之类的,不了解的可以看我之前博客 Link(前几天刚练了)
-
代码
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
83
84
85
86
87
88
89
90
91
92
93
94
95'''
Author: NEFU AB-IN
Date: 2022-04-10 13:01:10
FilePath: \Contest\b.1.py
LastEditTime: 2022-04-10 13:01:10
'''
def exgcd(a, b):
global k1, k2
if b == 0:
k1, k2 = 1, 0
return a
d = exgcd(b, a % b)
k1, k2 = k2, k1
k2 -= (a // b) * k1
return d
n = int(input())
m1, a1 = map(int, input().split())
flag = 0
for i in range(n - 1):
m2, a2 = map(int, input().split())
k1, k2 = 0, 0
d = exgcd(m1, m2)
if (a2 - a1) % d:
flag = 1
break
k1 *= (a2 - a1) // d
# k1' = k1 + k * (m2 // d) , k取任意整数
t = m2 // d
k1 = k1 % t # 取最小的k1
# x = a + km
a1 = k1 * m1 + a1
m1 = m1 // d * m2
if flag:
print(-1)
else:
print(a1 % m1) #x的最小正整数解
'''
48
2 1
3 2
4 1
5 4
6 5
7 4
8 1
9 2
10 9
11 0
12 5
13 10
14 11
15 14
16 9
17 0
18 11
19 18
20 9
21 11
22 11
23 15
24 17
25 9
26 23
27 20
28 25
29 16
30 29
31 27
32 25
33 11
34 17
35 4
36 29
37 22
38 37
39 23
40 9
41 1
42 11
43 11
44 33
45 29
46 15
47 5
48 41
49 46
2022040920220409
'''
-
-
试题 C: 质因数个数
-
试题 D: 矩形拼接
-
思路
结论不一定对,一共4,6,8三种情况
假设三个矩形a,b,c,如果任意两个矩形的其中各一条边,等于另一个矩形的一条边,说明最多6条边
如果能重合,就是4条边
其次就是- 如果三个矩形都有一条边相同,那么就是4条边
- 如果两个矩形都有一条边相同,那么就是6条边
其余情况8条边 (代码不准确)
-
代码
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'''
Author: NEFU AB-IN
Date: 2022-04-09 09:23:50
FilePath: \Contest\d.py
LastEditTime: 2022-04-09 11:29:16
'''
def judge(i, j, k):
ans = 8
# 0 0
if a[i][0] + a[j][0] == a[k][0]:
if a[i][1] == a[j][1]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
if a[i][0] + a[j][0] == a[k][1]:
if a[i][1] == a[j][1]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
# 1 0
if a[i][1] + a[j][0] == a[k][0]:
if a[i][0] == a[j][1]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
if a[i][1] + a[j][0] == a[k][1]:
if a[i][0] == a[j][1]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
# 0 1
if a[i][0] + a[j][1] == a[k][0]:
if a[i][1] == a[j][0]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
if a[i][1] + a[j][0] == a[k][1]:
if a[i][0] == a[j][1]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
# 1 1
if a[i][1] + a[j][1] == a[k][0]:
if a[i][0] == a[j][0]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
if a[i][1] + a[j][1] == a[k][1]:
if a[i][0] == a[j][0]:
ans = min(ans, 4)
else:
ans = min(ans, 6)
return ans
for _ in range(int(input())):
a1, b1, a2, b2, a3, b3 = map(int, input().split())
a = [0, [a1, b1], [a2, b2], [a3, b3]]
if (a1 in a[2] and a1 in a[3]) or (b1 in a[2] and b1 in a[3]):
print(4)
continue
print(min([judge(1, 2, 3), judge(1, 3, 2), judge(2, 3, 1)]))
-
-
试题 F: 重新排序
-
思路
就是先处理查询的总和为多少,并对每个点统计的数目打上标记,可以用前缀和和差分来解决,
再依据贪心的思想,数目大的 对上 标记多的,差分数组前缀和求和即可
总体复杂度 -
代码
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'''
Author: NEFU AB-IN
Date: 2022-04-09 09:28:11
FilePath: \Contest\f.py
LastEditTime: 2022-04-09 09:38:42
'''
n = int(input())
a = list(map(int, input().split()))
# 求原先的ans
s = [0] * (n + 2)
a = [0, *a]
for i in range(1, n + 1):
s[i] = s[i - 1] + a[i]
a = sorted(a[1:], reverse=True)
a = [0, *a]
b = [0] * (n + 2)
m = int(input())
ans1 = 0
for i in range(m):
l, r = map(int, input().split())
b[l] += 1
b[r + 1] -= 1
ans1 += (s[r] - s[l - 1])
stk = []
for i in range(1, n + 1):
b[i] += b[i - 1]
stk.append(b[i])
stk.sort(reverse=True)
stk = [0, *stk]
ans = 0
for i in range(1, n + 1):
ans += (a[i] * stk[i])
print(ans - ans1)
-
-
试题 G: 全排列的价值
-
思路
其实打出全排列的板子,再打几个数就可以发现规律
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171'''
Author: NEFU AB-IN
Date: 2022-04-09 09:43:50
FilePath: \Contest\g.py
LastEditTime: 2022-04-10 13:12:43
'''
from collections import Counter
N = 20
st, path = [0] * N, [0] * N
d = [Counter() for _ in range(N)]
def judge():
for i in range(1, n + 1):
cnt = 0
for j in range(1, i):
if path[j] < path[i]:
cnt += 1
d[i][cnt] += 1
def dfs(x):
if x == n + 1:
judge()
for i in range(1, n + 1):
print(path[i], end=" ")
print()
return
for i in range(1, n + 1):
if st[i] == 0:
path[x] = i
st[i] = 1
dfs(x + 1)
st[i] = 0
n = int(input())
a = [i for i in range(n + 1)]
dfs(1)
for i in range(1, n + 1):
print(i, d[i])
'''
5
1 2 3 4 5
1 2 3 5 4
1 2 4 3 5
1 2 4 5 3
1 2 5 3 4
1 2 5 4 3
1 3 2 4 5
1 3 2 5 4
1 3 4 2 5
1 3 4 5 2
1 3 5 2 4
1 3 5 4 2
1 4 2 3 5
1 4 2 5 3
1 4 3 2 5
1 4 3 5 2
1 4 5 2 3
1 4 5 3 2
1 5 2 3 4
1 5 2 4 3
1 5 3 2 4
1 5 3 4 2
1 5 4 2 3
1 5 4 3 2
2 1 3 4 5
2 1 3 5 4
2 1 4 3 5
2 1 4 5 3
2 1 5 3 4
2 1 5 4 3
2 3 1 4 5
2 3 1 5 4
2 3 4 1 5
2 3 4 5 1
2 3 5 1 4
2 3 5 4 1
2 4 1 3 5
2 4 1 5 3
2 4 3 1 5
2 4 3 5 1
2 4 5 1 3
2 4 5 3 1
2 5 1 3 4
2 5 1 4 3
2 5 3 1 4
2 5 3 4 1
2 5 4 1 3
2 5 4 3 1
3 1 2 4 5
3 1 2 5 4
3 1 4 2 5
3 1 4 5 2
3 1 5 2 4
3 1 5 4 2
3 2 1 4 5
3 2 1 5 4
3 2 4 1 5
3 2 4 5 1
3 2 5 1 4
3 2 5 4 1
3 4 1 2 5
3 4 1 5 2
3 4 2 1 5
3 4 2 5 1
3 4 5 1 2
3 4 5 2 1
3 5 1 2 4
3 5 1 4 2
3 5 2 1 4
3 5 2 4 1
3 5 4 1 2
3 5 4 2 1
4 1 2 3 5
4 1 2 5 3
4 1 3 2 5
4 1 3 5 2
4 1 5 2 3
4 1 5 3 2
4 2 1 3 5
4 2 1 5 3
4 2 3 1 5
4 2 3 5 1
4 2 5 1 3
4 2 5 3 1
4 3 1 2 5
4 3 1 5 2
4 3 2 1 5
4 3 2 5 1
4 3 5 1 2
4 3 5 2 1
4 5 1 2 3
4 5 1 3 2
4 5 2 1 3
4 5 2 3 1
4 5 3 1 2
4 5 3 2 1
5 1 2 3 4
5 1 2 4 3
5 1 3 2 4
5 1 3 4 2
5 1 4 2 3
5 1 4 3 2
5 2 1 3 4
5 2 1 4 3
5 2 3 1 4
5 2 3 4 1
5 2 4 1 3
5 2 4 3 1
5 3 1 2 4
5 3 1 4 2
5 3 2 1 4
5 3 2 4 1
5 3 4 1 2
5 3 4 2 1
5 4 1 2 3
5 4 1 3 2
5 4 2 1 3
5 4 2 3 1
5 4 3 1 2
5 4 3 2 1
1 Counter({0: 120})
2 Counter({1: 60, 0: 60})
3 Counter({2: 40, 1: 40, 0: 40})
4 Counter({3: 30, 2: 30, 1: 30, 0: 30})
5 Counter({4: 24, 3: 24, 2: 24, 1: 24, 0: 24})
'''1的有个,也就是
2的有个
3的有个
4的有个可以看出规律
先求出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
34
35
36
37'''
Author: NEFU AB-IN
Date: 2022-04-09 09:58:36
FilePath: \Contest\g.1.py
LastEditTime: 2022-04-10 12:33:52
'''
MOD = 998244353
n = int(input())
fa = 1
for i in range(2, n + 1):
fa = fa * i % MOD
fac = []
inv = [0] * (n + 1)
inv[1] = 1
for i in range(2, n + 1):
inv[i] = (MOD - MOD // i) * inv[MOD % i] % MOD
for i in range(2, n + 1):
fac.append(fa * inv[i] % MOD)
fac = fac[::-1]
fac = [0, *fac]
for i in range(1, n):
fac[i] = (fac[i] + fac[i - 1]) % MOD
ans = 0
for i in range(1, n):
ans = (ans + (i * fac[n - i] % MOD)) % MOD
print(ans)
# 200
# 495662656
-
其余的题不太确定
- E是骗分
- H打的贪心,我的思路是二分求出最优上升子序列,根据子序列的下标距离,判断距离之间能不能放k,如果不够放k,那么就需要考虑平推的问题
- I是打的线段树维护的最大值,思路比较糊
- J没做,但听说不难