给定序列 ,令 。,求:
考虑拆为每个 的贡献,得到:
而有个很好的事情是:已知 和 可以推出 ,所以后面那坨东西可以用很方便的 dp 来维护。那么问题就变为了求 ,事情就交给 EI 科技了。
有一张 个点、 条边的无向边带权图,请在每个点上表上一个
A/B/C
,最小化总代价(强制 点为A
, 点为B
),代价为每条边的代价的和,每条边的代价计算方式如下:
A B C A B C
将每个点拆成两个点,令每条边拆成两条边 ,那么看看这张新图的贡献表:
ST | TS | SS | TT | |
---|---|---|---|---|
ST | ||||
TS | ||||
SS | ||||
TT |
令 ,,,,那么唯独的区别就是 和 。但事实上,我们令图中所有的 都变为 ,会发现答案一定是缩小的,所以要么没有 要么没有 。所以 。
平面上最初有 个点 ,你可以进行 finite 次操作,每次操作选择两个已经存在的点,将其中点画在平面上。问最后能得到多少个整数点?坐标绝对值小于等于 ,保证任意三点不共线。
首先试着 check
一个整点 是否可以 plot。有三个条件要满足:
第三个条件是最为棘手的,rng_58
告诉我们,[第三个条件] 等价于:存在一组整数 使得 且 。证明他没告诉我们。一个比较有效的转化是:令 ,那么方程里就多了一个自由元 ,所以 的方程相当于被去掉了。而剩余的那个东西大致是一个二元裴蜀定理的形式,详见 [CERC2015]Looping Labyrinth(感谢 cyl)。而满足这个二元方程有解的整数对 一定可以被描述为 的形式。我们可以直接用裴蜀定理和拓展欧几里得算法来求出 和 ,下面介绍一个更为简洁的办法:
我们增量地维护 ,每次新增一个 ,我们试图通过类似欧几里得的办法把三个向量消成两个,剩下的一个是 ,不妨设 (不难发现这样的一对向量一定存在),那么令 ,生成空间不变,且可以使三个向量的幅长的最大值减小,于是便可以在 的时间内完成增量(Thanks https://codeforces.com/blog/entry/86100 @ecnerwala)。
于是斜角坐标系 内的所有坐标的最简分母为 的次幂的点都可以满足 [第三个条件]。事实上,我们可以进行如下的一个欧几里得法,使得对于斜角坐标系 来说,只有整数点满足 [第三个条件]:
xxxxxxxxxx
91for (int i = 1; i <= 100; i++)
2{
3 while (bs[1].x % 2 == 0 && bs[1].y % 2 == 0) bs[1].x /= 2, bs[1].y /= 2;
4 while (bs[2].x % 2 == 0 && bs[2].y % 2 == 0) bs[2].x /= 2, bs[2].y /= 2;
5 if ((bs[1] + bs[2]).x % 2 == 0 && (bs[1] + bs[2]).y % 2 == 0)
6 {
7 auto e1 = bs[1] + bs[2], e2 = bs[1] - bs[2]; bs[1] = e1, bs[2] = e2;
8 }
9}
正确性我也不知道为啥,我试了很多其它的办法都不行,然后就想到这个东西也许有用(逃)。然后只要将凸包上的点转为这个新的斜角坐标系下的点,然后用皮克定理()求出凸包内的可达的整点个数即可。复杂度可能是 。