C-D
1864C. Divisor Chain
题目简述,把一个数字x,通过减法变成1。被减数只能是减数的除法因子,且每个因子的使用次数不得超过两次。
从二进制的角度考虑除法因子。
比如十进制整数14,可以转成二进制1110。
那么可以每次减去(末尾最后一个1)10,100,然后得到1000。然后再依次减去100,10,1得到1,显然每个因子的使用次数最多是两次,非常地符合题意,这个方法太妙了。
时间复杂度 log(n)
空间复杂度 log(n)
# import sys
#
# sys.stdin = open('input.txt', 'r')
def divisor_chain(n):
k = n
bits = []
while k > 0:
bits.append(k % 2)
k = k // 2
# print(bits)
ans = [n]
k = n
for i in range(len(bits)-1):
if bits[i]:
k = k - (1 << i)
ans.append(k)
for i in range(len(bits)-2, -1, -1):
k = k - (1 << i)
ans.append(k)
print(len(ans))
print(' '.join(str(x) for x in ans))
def main():
tcn = int(input())
for _ in range(tcn):
n = int(input())
divisor_chain(n)
if __name__ == '__main__':
main()
1864D. Matrix Cascade
模拟法,一层一层向下传递,需要注意翻转状态的保留和翻转次数的计算。
1->3->5,一层一层的扩张。
其他技巧:差分数组,动态规划。
import sys
# sys.setrecursionlimit(10000)
def input_general():
return sys.stdin.readline().rstrip('\r\n')
def input_num():
return int(sys.stdin.readline().rstrip("\r\n"))
def input_multi(x=int):
return map(x, sys.stdin.readline().rstrip("\r\n").split())
def input_list(x=int):
return list(input_multi(x))
def main():
n = input_num()
arr = []
for _ in range(n):
s = input_general()
arr.append(s)
click = [[0 for _ in range(n)] for _ in range(n)]
need = [[0 for _ in range(n)] for _ in range(n)]
for i in range(n):
for j in range(n):
cl = 0
if i >= 1:
if j == 0:
cl = click[i - 1][j + 1] + need[i - 1][j]
elif j == n - 1:
cl = click[i - 1][j - 1] + need[i - 1][j]
else:
cl = click[i - 1][j - 1] + click[i - 1][j + 1]
if i >= 2:
cl -= click[i - 2][j]
cl += need[i - 1][j]
ne = (int(arr[i][j]) + cl) % 2
need[i][j] = ne
click[i][j] = cl + ne
# print(need, click)
print(sum(sum(row) for row in need))
if __name__ == "__main__":
cases = input_num()
for _ in range(cases):
main()