CF tracker

Edu List

https://codeforces.com/contest/1622

E. Math Test

n个学生,

m个题目

你知道每个学生 哪些题目对了哪些题目错了, 正确得分错误不得分

r[i] = 第i个学生的真实得分 = 正确题目得分之和

x[i] = 第i个学生的标准得分, 给定

问如何给题目 的分设置为 1~m 的排列

能让 sum |xi-ri| 最大, 求最大值

范围

n 10

m 1e4

2s

256mb

我的思路

这n很小, 就很想bitmask

但是 bitmask怎么用

想的是 分别计算 f(bitmask) = bitmask中的学生真实得分 >= 标准得分, 其它的学生 真实 < 标准

这样去掉了绝对值

然后如何算呢

这样得到 10个 不等式 和一个要求的最大值

正确错误的1/0串[i] * 题目分数设置 = r[i] >= x[i]

正确错误的1/0串[j] * 题目分数设置 = r[j] < x[j]

要求 max( 正确错误1/0加权和 * 题目分数设置)

有点像线性规划?


但一个是排列, 一个是又有大于等于, 又有小于等于, 并不知道怎么搞

閱讀全文 »

CF tracker

Edu List

https://codeforces.com/contest/1626

F. A Random Code Problem

给长度n的数组a

执行k次i=1..k

每次随机取下标idx,

ans+=a[idx]

a[idx] -= (a[idx] % i)

求 ans的期望, mod998244353

范围

n 1e7

1 <= a[0],x,y < M <= 998244353

1 <= k <= 17

a[i] = (a[i-1] * x + y)%M

3s

512mb

我的思路

这个操作就是 a[idx]变成贡献, 然后a[idx]变成不大于它的最大的i的倍数

这好几个神奇的地方, 首先n很大, 数组都是通过 递推式子给的, 这个递推式如果M小还有周期, 如果M大,不太知道怎么用

然后这个k <= 17 真的很小, 小到 甚至在想 bitmask

f[index][bitmask] = 贡献, 虽然这个状态大小都接受不了

但注意到第一次 的期望就是所有的平均数,

第二次也是, 当第二次选的偶数时, 那么第三次也是, 当第二次选的奇数时, 第三次 = 所有平均数 - 1/n

所以 经过第 i 轮 损失的量的 期望如果能算的话, 也是一个角度

算了下lcm(1…17) = 12252240, 也不小

而且 分支变化 状态也多

要快速计算 a[j] 可以用矩阵乘法, 但是 又要mod 又要加法, 算和也不知道怎么搞, 所以应该直接暴力掉?


12252240 似乎也可以, 每次相当于 n种操作, 那么就是所有 产生n 分, 第i份 处理i

只是在统计上,把它们加在一起, 这样每次 每个产生 1份处理的 和 n-1份没被处理的

r[i][w] += r[i-1][w]*(n-1)

r[i][next(w)] += r[i-1][w]

处理后的一定不大于当前的, 所以可以从大到小滚动掉,

所以可以滚动掉, 大概 O(k lcm(1…k)) ? 能过吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import math

def f(l,r):
s = 1
for i in range(l,r+1):
s=math.lcm(i,s)
return s

for i in range(1,17+1):
print(i, f(i,17))

1 12252240
2 12252240
3 12252240
4 12252240
5 12252240
6 12252240
7 12252240
8 12252240
9 12252240
10 4084080
11 4084080
12 371280
13 371280
14 28560
15 4080
16 272
17 17

题解

还真是这样, 问题在于我想多了, 17并不需要, 因为17虽然改变, 但是贡献是由16决定的

所以 lcm(1..16) = 720720 就相当的小了

就随便做了

总结

试了一下, 看来补atcoder和补cf还是开vp补 比较好, 这场VP了

E 没有在时间内写出来, 翻来覆去才写出, 花了接近1.5h, 还是应该想清楚所有情况才写,不要想一半写一半

F 细节想得有问题, 但总体的思路没问题

然后1e7 果然 for还是随便for的, 不直接给, 估计是因为read慢

参考

官方

https://atcoder.jp/contests/abc285/tasks

G

h * w 的格子 要用 1x1 和1x2 填满

上面有写 1,2,? 三种

1需要1x1覆盖

2需要1x2 覆盖(可以旋转成2x1)

? 任意

问 是否有可行方案

范围

h,w 300

3s

1024mb

我的思路

1 不需要关心, 只用关心2, 以及辅助2的?

看起来可以奇偶分边, 来做 二分图最大匹配 O(300^4) 感觉过不了

而且还有问题, 这里并不是要最大匹配, 只是要无冲突和匹配完所有2

另一个想法类似的, 能不能网络流, 还是奇偶分左右点, ?与?不连边, 但是 依然不知道如何表示 优先选2, 难道要费用流? 2的费用更低? 但似乎也没有”保证”

閱讀全文 »

CF tracker

Edu List

https://codeforces.com/contest/1633

E. Spanning Tree Queries

给n点,m边一个连通无向图

k个询问, 每次一个xi

你需要找一个生成树, 让 sum |wj-xi| 最小, wj为生成树的边的权重, 不需要输出具体方案

前 p个询问具体给出 xi

[p+1~k] 的询问 通过 q[j]=(q[j-1]a+b)%c 给出

输出所有询问的结果的xor

范围

n 50

m 300

wi, xi [0,1e8]

p 1e5

k 1e7

c [1,1e8]

4s

256mb

我的思路

对于一个具体的一个询问, 那么就是 经典的最小生成树算法, 让边权 = |wj-xi| 即可

但如果 把边排序了 并记录边的id

如果x变化, 但是排序后id顺序没有变, 那么最小生成树选择的边就不会边(虽然边权重变了)

那么排序后会有多少种情况呢, 感觉上 比 binom(50,25) 还多, 想x分割大于和小于的边,两个穿插

如果这个情况少, 那就变成 统计 情况内的边选择, 和对应>x小于x的个数与和来计算了

p 1e5 n 50 , m 300 是可以接受 暴力的

但是 k 1e7 一定要实现某种批量算法

閱讀全文 »

CF tracker

Edu List

https://codeforces.com/contest/1644

F. Basis

F(a数组,k数字) = 把a每个数组重复k次, 然后取 和a等长的前缀 [a_0_1,a_0_2...,a_0_k, a_1_1...a_1,k, a_2_1,...,a_2_k,...]

`x!=y, G(a数组,x数字,y数字) = 把a中所有x变成y, 所有y变成x

如果满足以下条件,则称a数组是b数组的父数组:

  • 存在 k使得F(a,k) = b
  • 或者 存在x!=y, G(a,x,y) = b

如果 有父数组链关系, 则称作祖先


问题, 给定n,k

构造系列 数组s={ s1,s2,..,sm}

每个si包含n个元素, si中的的值\in [1,k]

对于 任意的长n 值在 [1,k]的数组a, 至少在你给的s中存在一个si是a的祖先

问s的最小长度 mod 998244353

范围

n,k 2e5

6s

512mb

我的思路

si 通过 F,G的操作能变成任意数组

一个纯数字的数组, 那么通过F操作一定是自己的祖先,

两个不同的纯数字数组, 通过一次G操作 互为祖先

纯数字数组, 通过两次操作G一定是自己的祖先,

每个数组通过巨大k 操作, 都能变成纯数字数组


G的性质, 让数组的内容和具体值无关, 变成的一段一段的同样的值,(可以看成交换)

所以 比如 xxxyyyxxzz 是否能达到, 就是看 111221133 是否能达到

F的性质, 则是说不要考虑任何 x * w y * w z * w 的形状, 也就是能找到一个连续段的分割, 因为它总对应一个更小的


如果 k >= n, 那么就好了 [1,2,3,…,n], 啥都能变

考虑 k < n

两个没有 前缀 循环节的如何判断是否可以相互转化呢

1
2
3
n=5,k=4
1,2,3,3,4
1,2,2,2,3

一个猜想, 没有用完k的一定可以由 用完k的转化来, 因为至少有同色的个数 >= 2, 而且它不能转化回去(所以它的父一旦能被表示它则一定被表示, 所以它自身不需要存在)

两个序列之间如果可以转化 则 一定没有F操作, 否则形状会变有周期的,

而两个序列如果之间有G操作, 则不满足 从小到达命名1,2,3,4 的性质

综上, 需要统计

长度n, 用完k个,没有循环段, 且满足顺序赋值的个数(每个位置的值 <= 之前用的最大值+1)

有循环段很好算,枚举循环长度就行, 所以就找出满足 顺序赋值 的个数 再来减法


f[i][t] = 前i个最大命名为t的方案数

f[i][t] = f[i-1][t] * t + f[i-1][t-1] * 1, 分别是用前面一样的和用更大的

那么ans = f[n][k] - 有循环段的

直接搞是 O(n^2)

看成生成方程

$f_i(x) = f_{i-1}’(x) x + x f_{i-1}(x)$

$f_i(x)e^x = x (f_{i-1}e^x)’$

$令a_i = f_i(x)e^x$

再看 系数 $a[i][t] = a[i-1][t] * t$

所以 $a[n][t] = a[0][t] * t^n$

然后乘上$f[n] = a[n] * e^{-x}$ 就能得到 f[n][k]完了?

$a[0] = f[0] * e^x$


似乎有点问题

閱讀全文 »
0%