目录
一、P1102 A-B 数对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
1.hash表-一次遍历
2.双指针(同向,可以算滑动窗口)-排序
二、P8667 [蓝桥杯 2018 省 B] 递增三元组 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
1.排序+指针
2.排序+二分
三、12. 整数转罗马数字
1.模拟
2.模拟2-贪心
四、【模板】快速幂 - 洛谷
五、876. 快速幂求逆元 - AcWing题库
一、P1102 A-B 数对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
1.hash表-一次遍历
时复O(n),空复O(n)。
# 一次遍历
n, c = map(int, input().split())
nums = list(map(int, input().split()))
ans = 0
hash = {}
for x in nums:
if x - c in hash:
ans += hash[x - c]
if x + c in hash:
ans += hash[x + c]
hash[x] = hash.get(x, 0) + 1
print(ans)
2.双指针(同向,可以算滑动窗口)-排序
参考题解(题解 P1102 【A-B 数对】 - 洛谷专栏 (luogu.com.cn))。时复O(nlogn),空复O(1)。
# 双指针(同向,应该算滑动窗口)-排序
n, c = map(int, input().split())
nums = list(map(int, input().split()))
nums.sort()
ans = 0
# 维护区间差为c的窗口
left1, left2 = 0, 0
for right in range(n):
# 这里还有点二分的味道
while nums[right] - nums[left1] > c:
# 这里left不会超界,因为left最多到right就停
left1 += 1
while nums[right] - nums[left2] >= c:
left2 += 1
if nums[right] - nums[left1] == c:
ans += left2 - left1
print(ans)
二、P8667 [蓝桥杯 2018 省 B] 递增三元组 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
1.排序+指针
时复O(n^2),超时了。
代码:
# 排序+指针
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
a.sort()
b.sort()
c.sort()
ans = 0
j, k = 0, 0
for anum in a:
while j < n and b[j] <= anum:
# 将j调到对应位置
j += 1
if j < n:
bnum = b[j]
else:
continue
while k < n and c[k] <= bnum:
# 调整k
k += 1
jj = j
kk = k
while jj < n:
# a < b
bnum = b[jj]
while kk < n and c[kk] <= bnum:
# 调整kk
kk += 1
ans += n - kk
jj += 1
print(ans)
2.排序+二分
来自题解(P8667 [蓝桥杯 2018 省 B] 递增三元组 题解 - 洛谷专栏 (luogu.com.cn)),太帅了!时复O(nlogn),通过。
# 排序+二分
import bisect # 二分库
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
a.sort()
b.sort()
c.sort()
ans = 0
# 枚举处于中间的b
for bnum in b:
cnt_a = bisect.bisect_left(a, bnum)
cnt_c = n - bisect.bisect_right(c, bnum)
ans += cnt_a * cnt_c
print(ans)
三、12. 整数转罗马数字
1.模拟
class Solution:
def intToRoman(self, num: int) -> str:
# 模拟
ans = ''
while num > 0:
if num <= 9:
if num == 9:
ans += 'IX'
num -= 9
elif num == 4:
ans += 'IV'
num -= 4
elif num >= 5:
ans += 'V'
num -= 5
while num >= 1:
ans += 'I'
num -= 1
elif num <= 99:
if num >= 90:
ans += 'XC'
num -= 90
elif 49 >= num >= 40:
ans += 'XL'
num -= 40
elif num >= 50:
ans += 'L'
num -= 50
while num >= 10:
ans += 'X'
num -= 10
elif num <= 999:
if num >= 900:
ans += 'CM'
num -= 900
elif 499 >= num >= 400:
ans += 'CD'
num -= 400
elif num >= 500:
ans += 'D'
num -= 500
while num >= 100:
ans += 'C'
num -= 100
else:
while num >= 1000:
ans += 'M'
num -= 1000
return ans
2.模拟2-贪心
来自官方题解(. - 力扣(LeetCode))。
class Solution:
VALUE_SYMBOLS = [
(1000, "M"),
(900, "CM"),
(500, "D"),
(400, "CD"),
(100, "C"),
(90, "XC"),
(50, "L"),
(40, "XL"),
(10, "X"),
(9, "IX"),
(5, "V"),
(4, "IV"),
(1, "I"),
]
def intToRoman(self, num: int) -> str:
# 模拟2
roman = ''
for value, symbol in Solution.VALUE_SYMBOLS:
while num >= value:
num -= value
roman += symbol
if num == 0:
break
return roman
四、【模板】快速幂 - 洛谷
'''
快速幂模板题
'''
a, b, p = map(int, input().split())
def binpow(a, b, p):
res = 1
a %= p
while b > 0:
# 将每一位的值乘上去(指数是加,幂数是乘)
if b & 1:
res = res * a % p # 对当前值进行取模
b >>= 1
a = a * a % p
return res
print(f"{a}^{b} mod {p}={binpow(a, b, p)}")
五、876. 快速幂求逆元 - AcWing题库
# 辗转相除法求最大公因数
def gcd(a, b):
if a < b:
return gcd(b, a) # 大的放前面
while b > 0:
a, b = b, a % b
return a
def qmi(a, n, mod):
ans = 1
a %= mod
while n:
if n & 1:
ans = ans * a % mod
a = a * a % mod
n >>= 1
return ans
n = int(input())
for _ in range(n):
a, q = map(int, input().split())
if gcd(a, q) != 1:
print('impossible')
continue
print(qmi(a, q - 2, q))
完
感谢你看到这里!一起加油吧!