标签:
文章链接:http://www.cnblogs.com/Asm-Definer/p/4434601.html
看巨神们都去虐ZJOI了,蒟蒻只能默默地码着CQOI的解题报告……
CQOI的难度分布也是挺神奇的,五小时五道题,三(或四)道水题一道神题(只是我认为...),我猜让我去考我一定会写不完D题然后滚去备战高考= =
从区间[L, H]中选出N个数(可以重复),求取出的N个数的最大公约数恰好为K的方案数。
其中$1 \leq L, H, N \leq 10^9, H - L \leq 10^5$
刚开始还以为这是道简单的莫比乌斯反演题,推了半天公式,发现是个依赖$\lfloor H / K \rfloor $的式子
$$\sum_{d=1}^{H/K} \mu(d) (\frac{H}{d*K} - \frac{L-1}{d*K})^N$$(由于LaTeX打取整式太不方便所以这个式子没有考虑细节)当$H/K$很大的时候mu就无法预处理了。
后来衡中的JSX同学(http://55242.cf/)告诉我一个不错的思路:对较小的mu用线性筛预处理,对较大的mu直接暴力分解质因数。而当d比较大的时候会有很多$(\frac{H}{d*K} - \frac{L-1}{d*K})$为0的区间,遇到这些区间就跳转一下就可以了。粘一下他的核心代码:
1 for(int i = 1;i <= R;++ i) {
2 if((R/i) == (L/i)) {
3 i = min((LL)R/(R/i) ,(LL)L / i ? L/(L/i) : INF);
4 continue;
5 } else {
6 ans += (LL)quickpow((R/i)-(L/i),N) * get_mu(i);
7 ans %= mod;
8 }
9 }思路简单,效率也很不错。
不过……有强迫症的同学可能会想……如果这道题表达式的后半部分不是$(\frac{H}{d*K} - \frac{L-1}{d*K})$而只有$\frac{H}{d*K}$,这个式子就不会很快变成0了。这样还是否可做呢?
考虑到在取整后$\frac{H}{d*K}$的取值只有$\sqrt{\frac{H}{K}}$个,如果我们能快速地求出莫比乌斯的前缀和(梅腾斯函数),就可以在$O(1)$的时间内求出一段相等的区间的贡献了。
这个$M(N) = \sum_{i=1}^N \mu(i)$看起来似乎很难的样子……其实我们可以这样转化:
$$M(N)= \sum_{i-1}^N (\sum_{d|i}\mu(d) - \sum_{d|i \land d \neq i}\mu(d) ) \= 1 - \sum_{i=1}^N \sum_{d|i \land d \neq i} \mu(d) \\= 1 - \sum_{i‘=2}^N \sum_{d=1}^{\lfloor \frac{N}{i‘} \rfloor} \mu(d) \\ = 1 - \sum_{i‘=2}^N M(\lfloor \frac{N}{i‘}\rfloor)$$
这样,我们就可以在预处理出前$10^7$项梅腾斯函数后在处理较大的N时对
$\lfloor \frac{N}{i‘}\rfloor$分块递归就可以快速地求出超过$10^7$的梅腾斯函数了。(这个带下取整的递推式复杂度究竟是多少呢……反正我不会分析……不过目测我们需要计算的次数非常少,所以这个复杂度就足够了。
然而……出题人表示我们都太Simple啦,Sometimes Naive!我们观察一下题目中的条件……“$H - L \leq 10^5$"......注意到当N个数不全相同的时候,它们的最大公约数一定不会超过其中任意两个不同数的差。于是……我们只需要将边界除以K后递推”N个数不全相同且最大公因数为i($i \leq 10^5$)"的方案数,最后特判一下N个数都相同的情况,加上递归得到的F(1)就是答案了,复杂度是优美的$(H-L) log (H-L)$。
在一个无向网络的最短路径构成的DAG上求最大流。$|V| \leq 500, |E| \leq 100000 $
似乎不需要分析了,除了最短路+网络流外没有什么其他的东西……
注意到这里的原图是个稠密图,使用$O(|V|^2)$的Dijkstra 可以得到很好的运行效率。
给出n个区间,每个区间有一个权值$P_i$;共m次询问,每次询问覆盖$x_i$点的所有区间中权值最小的$K_i$个区间的权值和。数据规模 $\leq 10^5$
很经典的可持久化线段树的模型。对所有权值离散化后在所有点构造可持久化线段树,询问时对线段树做区间查询。
已知整数$n, t, a_k(1 \leq k \leq n), m,$ 求出能使$$\sum_{k=0}^n a_k x^k = \sum_{k=1}^n b_k (x-t)^k $$的b数列的第m项。
其中 $a_k$满足递推式:$$k = 0时,a_k = 1;k > 0时,a_k = (1234*a_{k-1} + 5678) \mod 3389$$.
其中 $0 < n \leq 10^3000, 0 \leq t \leq 10000, 0 \leq n-m \leq 5.$
天哪……为何这位出题人这么喜欢加这么奇怪的数据范围限制……
首先,对于多项式来说,这个x的取值是任意的。所以我们可以用x+t替换x代入条件,得到
$$\sum_{k=0}^n a_k (x + t)^k = \sum_{k=0}^n b_k x^k$$
$$ \sum_{k=0}^n b_k x^k = \sum_{k=0}^n a_k \sum_{j=0}^k \tbinom{j}{k} x^j t^{k-j} $$
考虑枚举k-j的值:$$\sum_{k=0}^n b_k x^k=\sum_{i=0}^n \sum_{d=0}^{n-i} a_{i+d} \tbinom{i}{i+d} t^d x^i $$
对齐每一项的系数,得到:
$$b_m = \sum_{d=0}^{n-m} a_{m+d} \frac{(m+d)! t^d}{m!d!}$$注意到n-m不超过5,我们可以先得出$a_m$的值,递推(n-m)次把答案加起来即可。
考虑到n和m都可以很大,这里在求$a_m$的值时要用到10-based的矩阵快速幂。
我真的是昨天才知道这个“标识”的“识”应该念zhi(4)……我真是文盲……
思路是轮廓线dp,dp状态记录扫描到某个位置时“是否需要连接左边的方格”,“当前已经放下了多少个L”和当前的轮廓。(这里“轮廓”的含义是有哪些列需要连接上方垂下来的竖直线)。由于任意状态垂下来的竖直线最多只有3条,轮廓的状态数很少(暴力枚举一下发现只有4090左右),可以利用离散化减少压位的数量。
但以我极差的代码能力实在卡不进1s的时间限制……看了这位神犇的博客之后才知道上述的状态中“不合法状态”和“不可能到达的状态”都很多,所以用记忆化搜索来实现可以大大缩短枚举的时间。
标签:
原文地址:http://www.cnblogs.com/Asm-Definer/p/4434601.html