C - Sum of gcd of Tuples (Easy)
遍历abc即可
D - RGB Triplets
RGB做前缀和
然后遍历后两个数,求第一个的前缀和。而且在遍历时减去
i
−
j
=
j
−
k
i-j=j-k
i−j=j−k的情况。
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(1000)
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
n = int(fp.readline())
s = fp.readline().strip()
s = '@' + s
r, g, b = [0] * (n + 1), [0] * (n + 1), [0] * (n + 1)
for i in range(1, n + 1):
r[i], b[i], g[i] = r[i - 1], b[i - 1], g[i - 1]
if s[i] == 'R':
r[i] += 1
elif s[i] == 'G':
g[i] += 1
else:
b[i] += 1
ans = 0
for i in range(1, n + 1):
for j in range(1, i + 1):
ci = s[i]
cj = s[j]
if ci == cj:
continue
c_list = 'RGB'
c = '@'
for x in c_list:
if x not in [ci, cj]:
c = x
break
k = 2 * j - i
if c == 'R':
t = r[j - 1]
if k >= 0 and s[k] == 'R':
t -= 1
elif c == 'B':
t = b[j - 1]
if k >= 0 and s[k] == 'B':
t -= 1
else:
t = g[j - 1]
if k >= 0 and s[k] == 'G':
t -= 1
ans += t
print(ans)
if __name__ == "__main__":
main()
E - Sum of gcd of Tuples (Hard)
遍历gcd的值
注意到每个值g的方案
f
(
g
)
f(g)
f(g)要减去g的倍数
f
(
2
g
)
,
f
(
3
g
)
.
.
.
f(2g),f(3g)...
f(2g),f(3g)...
这是一个调和级数的时间复杂度
如果
n
n
n范围扩大需要欧拉反演和莫比乌斯反演的知识,弱苣不会了
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(1000)
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
n, k = map(int, fp.readline().split())
mod = 10 ** 9 + 7
def pw(a, x):
if x == 1:
return a
t = pw(a, x >> 1)
if x & 1:
return t * t * a % mod
else:
return t * t % mod
f = [0] * (k + 1)
for i in range(k, 0, -1):
x = k // i
f[i] = pw(x, n)
for j in range(2 * i, k + 1, i):
f[i] = (f[i] - f[j]) % mod
ans = 0
for i in range(1, k + 1):
ans = (ans + i * f[i]) % mod
print(ans)
if __name__ == "__main__":
main()
F - Select Half
选和不选的DP题,闭着眼睛写
设
f
(
i
,
k
)
f(i,k)
f(i,k)为选中i位置的数后前面一共选中了k个数的最大和
g
(
i
,
k
)
g(i,k)
g(i,k)为不选中i位置的数周前面一共选中了k个数的最大和
f
(
i
,
k
)
=
f
(
i
−
1
,
k
−
1
)
+
a
[
i
]
f(i,k)=f(i-1,k-1)+a[i]
f(i,k)=f(i−1,k−1)+a[i]
g
(
i
,
k
)
=
m
a
x
(
f
(
i
−
1
,
k
)
,
g
(
i
−
1
,
k
)
)
g(i,k)=max(f(i-1,k),g(i-1,k))
g(i,k)=max(f(i−1,k),g(i−1,k))
空间复杂度用滚动数组优化
乍看下时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)但实际上k的取值范围很小,我这里取的稍微放大了一点范围
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(1000)
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
n = int(fp.readline())
a = list(map(int, fp.readline().split()))
f = [[-10 ** 18] * n for i in range(2)]
nf = [[-10 ** 18] * n for i in range(2)]
nf[0][0] = 0
op = 0
for i in range(n):
mk = i // 2 + 1
# max k
for k in range(mk, max(-1, mk - 4), -1):
f[1 ^ op][k] = nf[1 ^ op][k] = -10 ** 18
# choose
for k in range(mk, max(0, mk - 4), -1):
f[1 ^ op][k] = max(f[1 ^ op][k], nf[op][k - 1] + a[i])
# not choose
for k in range(mk, max(-1, mk - 4), -1):
nf[1 ^ op][k] = max(nf[op][k], f[op][k])
op = 1 ^ op
K = n // 2
ans = max(f[op][K], nf[op][K])
print(ans)
if __name__ == "__main__":
main()