C - Sum of gcd of Tuples (Easy)
遍历abc即可
D - RGB Triplets
RGB做前缀和
然后遍历后两个数,求第一个的前缀和。而且在遍历时减去 i − j = j − k i-j=j-k i−j=j−k的情况。
python
# -*- 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范围扩大需要欧拉反演和莫比乌斯反演的知识,弱苣不会了
python
# -*- 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的取值范围很小,我这里取的稍微放大了一点范围
python
# -*- 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()