C题
签到题。会python的permutations 或者C++的next_permutation就能做。
D题
乍一看很简单,把所有元素折半求最小公倍数lcm,然后求lcm的奇数倍即可。但是有坑:
比如6 4这种情况,lcm=6 但6=61 6=41.5,因此无法满足要求。原因是4折半后为2,导致求得的lcm可以被2整除,如6/2不为半数。去掉这种情况就能AC。
# -*- 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(200050)
def gcd(x, y):
if x > y:
x, y = y, x
while x:
x, y = y % x, x
return y
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
n, m = map(int, fp.readline().split())
a = list(map(int, fp.readline().split()))
for i in range(n):
a[i] = a[i] // 2
gm = a[0]
for i in range(1, n):
g = gcd(a[i], gm)
gm = gm // g * a[i]
for i in range(n):
if (gm // a[i]) % 2 == 0:
print(0)
return
ans = m // gm - (m // (2 * gm))
print(ans)
if __name__ == "__main__":
main()
E题
下面两个很不错的题。
本题考察如何按位置来计数。首先题目可以把 f ( S , T ) f(S,T) f(S,T)转换为求 f ( S ) = S ⊕ T f(S)=S \oplus T f(S)=S⊕T下按照原规则计算,然后答案乘上 2 n 2^n 2n。
如 第二个例子中 5 8
可以看到以下 2 2 2^2 22组是等价的
( 1 , 0 ) , ( 0 , 0 ) (1,0) ,(0,0) (1,0),(0,0)
( 0 , 0 ) , ( 1 , 0 ) (0,0),(1,0) (0,0),(1,0)
( 1 , 1 ) , ( 0 , 1 ) (1,1),(0,1) (1,1),(0,1)
( 1 , 0 ) , ( 0 , 0 ) (1,0),(0,0) (1,0),(0,0)
现在原题就转换为求 s ∈ 0... 2 n s \in {0...2^n} s∈0...2n的 f ( s ) f(s) f(s)之和。
显然c应该从大到小排序。
如果按照每个c从第一位到第n位来计数,那么不难利用组合数推出一个 O ( n 2 ) O(n^2) O(n2)算法。但是时间不够。
比较巧妙的计数方法是将每一位的计算拆开来。
假设当前已经到了第i位(i从1开始计数)
例如要求的c数组长度为3,可以列出8个异或值。
1 , 1 , 1 1 , 0 , 0 1 , 0 , 1 1 , 1 , 0 0 , 0 , 0 0 , 0 , 1 0 , 1 , 0 0 , 1 , 1 1,1,1\\1,0,0\\1,0,1\\1,1,0\\0,0,0\\0,0,1\\0,1,0\\0,1,1 1,1,11,0,01,0,11,1,00,0,00,0,10,1,00,1,1
看第3位,他对答案的贡献是3+2+1+2=8(从上往下)
我们可以将其拆成两部分,第一部分是“只要填了1就可以贡献1”
由于这部分和其他无关,因此贡献值一共为 2 n − 1 2^{n-1} 2n−1
第二部分是“前面的某一位填了1因此要多贡献1”
这部分仅仅和前面的那一位相关(当然这一位也要填1),因此贡献值是 2 n − 2 ∗ ( i − 1 ) 2^{n-2}*(i-1) 2n−2∗(i−1)
这样答案就已经出来了。
回到样例,例如第一组 1 , 1 , 1 1,1,1 1,1,1中,第一部分贡献1,第二部分分别由前面的数字贡献了1+1,因此是3;第三组 1 , 0 , 1 1,0,1 1,0,1中,第一部分贡献1,第二部分由第一位1贡献了1,因此是2.
# -*- 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(200050)
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()))
a.sort(reverse=True)
mod = 10 ** 9 + 7
pw = [1] * (n + 1)
for i in range(1, n + 1):
pw[i] = pw[i - 1] * 2 % mod
ans = 0
for i in range(n):
ans += (pw[n - 1] + pw[n - 2] * i) * a[i]
ans = ans * pw[n] % mod
print(ans)
if __name__ == "__main__":
main()
F题
看到这种求shift的题,第一感觉一定是将匹配串重复一遍。
好吧,既然说到了模式串和匹配串,那么不得不说到kmp。单纯的kmp似乎没什么思路,但是如果将每个数组相邻的数进行异或操作,就变成了kmp模板题。
# -*- 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 get_next(p):
p = [0] + list(p)
m = len(p)
ne = [0] * m
i, j = 2, 0
while i < m:
while j and p[i] != p[j + 1]:
j = ne[j]
if p[i] == p[j + 1]:
j += 1
ne[i] = j
i += 1
return ne
def kmp_match(s, p, ne):
s = [0] + list(s)
p_len = len(p)
p = [0] + list(p)
i, j = 1, 0
n, m = len(s), len(p)
m_list = []
while i < n:
while j and j + 1 < m and s[i] != p[j + 1]:
j = ne[j]
if j + 1 < m and s[i] == p[j + 1]:
j += 1
if j == p_len:
bi, ei = i - p_len + 1, i
j = ne[j]
m_list.append(bi - 1)
i += 1
return m_list
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()))
b = list(map(int, fp.readline().split()))
a = a + a
da, db = [], []
for i in range(2 * n - 2):
da.append(a[i + 1] ^ a[i])
for i in range(n - 1):
db.append(b[i + 1] ^ b[i])
ne = get_next(db)
m_list = kmp_match(da, db, ne)
for i in m_list:
print(i, a[i] ^ b[0])
if __name__ == "__main__":
main()