总体来说本期比较简单
C - Maximum Volume
答案显然是O(N3)O(N^3)O(N3)
D - Banned K
先统计总的,然后减去选到的那个数再重新计算
E - Dividing Chocolate
既然n范围是10,那么在n的宽度上做一个位操作,若i位与i+1位之间有切割,i位设为1,枚举横方向的切割方案,然后在竖方向上做贪心
# -*- 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, m, K = map(int, fp.readline().split())
a = []
for i in range(n):
s = fp.readline().strip()
a.append(s)
sm = [[0] * m for _ in range(n + 1)]
for j in range(m):
for i in range(n):
sm[i + 1][j] = sm[i][j] + ord(a[i][j]) - ord('0')
ans = 10 ** 18
for mask in range(1 << (n - 1)):
last = 0
temp = []
div_cnt = 0
ac = 1
for j in range(n):
if mask >> j & 1 or j == n - 1:
b = []
for k in range(m):
x = sm[j + 1][k] - sm[last][k]
if x > K:
ac = 0
b.append(x)
last = j + 1
temp.append(b)
if mask >> j & 1:
div_cnt += 1
if ac == 0:
continue
l = len(temp)
t = [0] * l
for j in range(m):
d = 0
for i in range(l):
t[i] += temp[i][j]
if t[i] > K:
d = 1
if d:
div_cnt += 1
for i in range(l):
t[i] = temp[i][j]
ans = min(ans, div_cnt)
print(ans)
if __name__ == "__main__":
main()
F - Knapsack for All Segments
观察了一下,发现在做到 i位时,可以去计算F(i,sum)F(i, sum)F(i,sum)
其中sum是当前计算的和,F代表方案数
F(i,sum)=∑F(j,sum−a[i])∗(n−i)F(i,sum)=\sum F(j,sum-a[i])*(n-i)F(i,sum)=∑F(j,sum−a[i])∗(n−i)
但是这样是O(N2∗S)O(N^2*S)O(N2∗S)的三重循环,因此要记录一下前缀和G(sum)=∑F(i,sum)G(sum)=\sum F(i,sum)G(sum)=∑F(i,sum)
# -*- 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, S = map(int, fp.readline().split())
a = list(map(int, fp.readline().split()))
dp = [0] * (S + 1)
mod = 998244353
ans = 0
for i in range(n):
if a[i] == S:
ans += (i + 1) * (n - i)
ans %= mod
elif S - a[i] > 0:
ans += dp[S - a[i]] * (n - i)
ans %= mod
for j in range(S, -1, -1):
if j >= a[i]:
dp[j] = (dp[j] + dp[j - a[i]]) % mod
dp[a[i]] += i + 1
dp[a[i]] %= mod
print(ans)
if __name__ == "__main__":
main()
本文介绍了几个编程挑战,包括C-MaximumVolume的立方级复杂度、BannedK的计数策略、DividingChocolate的位操作方法及F-Knapsack的前缀和优化,涉及动态规划和时间效率提升。

4545

被折叠的 条评论
为什么被折叠?



