• 2021-03 杂题泛做


    Codeforces 1100F

    又是维护线性基的 (trick),考虑使用扫描线回答询问

    在插入线性基的过程中给每一位存上个 (position) 最大的 (1) 就行了

    因为是贪心,希望 (l) 大的询问也可以用到这个 (1)

    sequence

    考虑每个序列的 (And) 和最多变化 (log)

    (ST) 表维护区间 (And) 和,然后逐段二分得到修改的点

    剩下的扫描线套线段树,线段树上的操作是 ( exttt{耐(ruo)人(zhi)寻(dao)味(jia)}) 的,值得思考

    uoj21

    考虑如何求 (max(sumfrac{a_i(x-1)}{x}))

    想到的一个做法是枚举有意义的 (x),但是这种 (x) 很多

    但是不难观察到相邻的两个有意义的数之间贡献是直接 (+1) 的,差分就能维护了

    但是这样需要整除分块来进行加减

    每个数上的答案是显然可以快速统计的,那么 (O(nln n)) 即可

    uoj22

    先把序列从大到小排一下,因为先模后面再前面没有意义

    第一问:(dp_{i,j}) 表示前 (i) 个数,(j) 可否为当前可行答案

    从当前向下一个转移,最后从 ([0,a_n-1]) 选答案,实现的时候数组甚至可以一维

    按照上面的思路,设 (f_j) 表示当前答案为 (j) 的方案数,转移找一个 (le j) 的数即可

    显然转移的时候 ([j\% a_i,j-1])(a_i) 是可以任意插到排列里面的,预处理排列数即可

    值得注意的是在计算的开始 (f[x]) 要把大于 (x)(a_i) 插入到排列里面

    uoj23

    主思想是每个边当作 (x) 的话长度为 (L) 的边的数量就是 ([x^L]f(x)),以前见过,这次加深了印象

    考虑环上点的贡献:对于一个点如果到环顶的距离分别为 (a,b) 考虑每个边是 (x^1) 的话就是链顶 (P(x) imes (x^a+x^b))

    写的时候和一般的仙人掌差不多,就是先跑最短路,然后找环,(50’) 的做法就是暴力维护多项式

    值得注意的一点是记得维护环的几个链的重边的乘积

    (70) 做法把每个环上的贡献算一算,然后对环的部分分治乘法就行了,每个节点扔一个站位的 (x^0) 把前面的答案收集一下


    (Theta(nlog^3 n)) :考虑点分治

    对于仙人掌,如法炮制树上点分治的做法,使断开与其相邻的边之后子联通块的大小尽量小

    重心连出去的边分为向上和向下,可以快速得到父链多项式,对于向下的边求子树的加和多项式,进行卷积即可,向上的直接加入答案

    如果向上的边是个环,需要对环上的点都处理一下

    仙人掌点分使用圆方树,每个方点上放 (SZ) 环的权值,求带权重心即可

    这个做法代码不很会写,先鸽掉,还有俩 (log) 的做法,也不会

    uoj31

    如果当前序列不合法,那么必然是一个前缀和为负,那么找到后面最近的一个 (1) 翻过来就行

    实现需要维护所有 (1) 的位置和前缀和,分别使用单调指针扫和数据结构维护即可

    建议树状数组,因为线段树被卡常了

    其实貌似没必要用数据结构,维护一个变量就行了,我思维僵化了

    uoj33

    本来对这个 (gcd(i,j)=k) 想的是反演,其实是复杂了

    如果能求到 (ans[i]) 表示 (gcd)(i) 的倍数的数的个数,最后套上一个 (Theta(nln n)) 的容斥可以得到原答案

    对原树跑点分治,值得指出的是这个树是有根的,对于当前分治重心向上的子联通块需要特殊处理

    • 都在分治重心 (x) 子树点对,维护一个表示深度的桶和一个深度的倍数,然后合并答案

    • 对于一个在父联通块,一个在子树里面的点对

      显然对于父链上的点还是可以处理如上的两个桶,对于 (ans[i]) 的增量应当为两个倍数桶的乘积

      对于子树的倍数桶要求开头不是 (0) 的部分的和,需要大量记录,空间不能接受

      仍旧使用根号分治,对于 (ge sqrt n) 的部分暴力,预处理答案即可(也可以说是记忆化吧)

    [ exttt{Talk is cheap,Coding is Impossible} ]

    异或图

    斯特林反演:

    [f(n)=sum_i (-1)^i egin{Bmatrix}n \i end{Bmatrix} g(i) ]

    [g(n)=sum_i (-1)^i egin{bmatrix} n\ iend{bmatrix} f(i) ]

    将排列斯特林数和组合斯特林数调换位置也是正确的,这个使用结论:

    [[m=n] =(-1)^nsum_{i} (-1)^iegin{Bmatrix} n\ i end{Bmatrix} egin{bmatrix}i\ mend{bmatrix} ]

    或者

    [[m=n] =(-1)^nsum_{i} (-1)^iegin{Bmatrix} i\ m end{Bmatrix} egin{bmatrix}n\ iend{bmatrix} ]

    可以证明,而这两个结论使用上升下降幂公式硬上,发现对于多项式系数必然一致,那么证毕

    然而本题中并不使用上面的式子,而是考虑:

    [f(x)=sum_{i=x}^n egin{Bmatrix} n\ iend{Bmatrix}g(i) ]

    可以得到

    [g(x)=sum _ {i=x}^n egin{bmatrix} n\ iend{bmatrix}(-1)^{i-x} f(i) ]

    证明是类似的,本质上是一个上三角变成了下三角


    图状压下来之后只有 (55) 位,在一个线性基的射程范围之内

    (dfs) 枚举哪些数放到了一个集合里面,那么不在同一个集合里面的边不能存在,所以可以建一个异或方程组的线性基

    线性基里面的异或结果不能存在,那么得到 (res=2^{n-num})

    把结果累加到 (f_{cnt}) 里面,最后使用斯特林反演即可

    关于高斯消元解异或方程组,解的个数是把剩下的全消成 (0) 的时候 (2) 的剩下的行数次方

    uoj32

    直接对 (1) 所在的联通块考虑,题目求的也就是路径上不存在负环的 (x) 的个数

    如果出现了一个负环,那么影响的一定是它的后继的答案区间,所以先 (floyd) 传递闭包找到联通性

    考虑 (Bellman-Ford)(f[n][i][j]) 表示环上的 (col) 的和为 (j) 时,在点 (i) 处走了 (j) 步的最短路

    最短路一定是简单路径,那么如果 (f[n][i]>f[n-1][i]) 说明存在一个负环

    这里不考虑 (k) 列出来的式子如上,那么考虑上 (k) 就好说了:

    [min{f[n][i][k]+kx}ge min{f[n-1][i][j]+jx} ]

    如果满足该式子,那么当前的 (x) 符合条件

    对于上面的不等式,枚举所有的 (k),得到答案之后求交集,拆掉一个 (min{})

    剩下的一个也跟着枚举 (j) ,做出来之后求并集即可

    实现的时候我完全反过来写的,先交后并,最后总方案容斥

    值得指出的是,实现的时候可以把 (inf) 设成 (2 imes10^{18}),会方便一些

    uoj48

    直接把第一个数分解,然后后面的数一个一个对着质因子分,除掉最小的一个

    uoj49

    对于当前的 (s) 选择箱子的手段一定是在两边找距离最小的一个,同时选择的起始点一定有箱子

    关于第二个结论直接展开所用的时间的式子,是一个绝对值方程,这个东西显然有奇数个箱子的话是中位数,偶数个箱子放到左右两边答案一样

    显然的二分答案 (mid),然后枚举每个 (x_i) 作为中位数所在的位置

    设当前区间 ([l,r]) 满足这个坐标是中位数所在的位置,统计遍历这些区间所使用的时间,这个通过前后缀和能做到 (O(1))

    由于 (x_i) 位置本身可能有箱子,那么其实这样的 ([l,r]) 可能有多个,但是当 (x_i) 递增的时候这些区间必然是单调右移的

    证明可以考虑比较 (x_{i-1}) 的尾状态和 (x_i) 的初始状态

    尾状态的 (l)(x_{i-1}) 中有 (frac{mid}2) 个数,这样是满足下一个中位数点的初始状态的,证毕

    一道难题实现一定是大关,所以它很难写

    其实可以维护 (lnow,rnow) 两个变量表示左右边界的取用数量,更新区间的时候快速增量,也是可以保证复杂度的正确性的

    uoj50

    把式子捋一下:

    [f(n)=frac12sum_{jin A}inom {i-1}{j} sum_{k}inom{i-1-j}{k} f(i-1-j-k)f(k) ]

    然后设:

    [g(n)=sum_{i=1}^n frac{f(i)}{i!}frac{f(n-i)}{(n-i)!} ]

    那么把组合数展开之后得到

    [frac{f(n)}{(n-1)!}=frac12sum_{j}^nfrac{A_j}{j!}g(n-1-j) ]

    那么再傻也能给看出来 (f(n))(g(n)) 都是卷积,先硬上 (cdq\_NTT)

    但是直接写还是过不了样例,那么问题出在了一种叫做 ( exttt{我卷我自己}) 的卷积模型上面

    也就是说对于 ([1,mid]×[l,mid]) 的贡献在分治区间左端点为 (1) 的时候无法进行正确贡献

    那么转移 (G) 的时候处理的长度为 (r-l+1) 的数组中,如果 (i<l) 那么放 (2F[i])(lle ile mid)(F[i]) 反之放 (0) 就行

    即如下:

    inline void solve(int l,int r){
        if(l==r){if(l==1) F[1]=1; else F[l]=mul(F[l],mul(i2,fac[l-1])); return ;} 
        int mid=(l+r)>>1; solve(l,mid); 
        int lim=1; while(lim<=(r-l+1+mid-l+1)) lim<<=1; 
        for(reg int i=0;i<=r-l;++i) 
        	if(i<l) H[i]=mul(F[i],mul(2,ifac[i])); 
        	else if(i<=mid) H[i]=mul(F[i],ifac[i]); 
            else H[i]=0; 
        For(i,0,mid-l) I[i]=mul(F[i+l],ifac[i+l]);
        for(reg int i=mid-l+1;i<=r-l;++i) I[i]=0; 
        for(reg int i=r-l+1;i<lim;++i) H[i]=I[i]=0;
        NTT(H,lim,1); NTT(I,lim,1); 
        for(reg int i=0;i<lim;++i) H[i]=mul(H[i],I[i]); 
        NTT(H,lim,-1); 
        for(reg int i=mid+1;i<=r;++i) G[i]=add(G[i],H[i-l]);
        for(reg int i=0;i<=r-l;++i) H[i]=mul(A[i],ifac[i]);
        for(reg int i=0;i<=mid-l;++i) I[i]=G[i+l];
        for(reg int i=mid-l+1;i<=r-l;++i) I[i]=0;
        for(reg int i=r-l+1;i<lim;++i) H[i]=I[i]=0; 
        NTT(H,lim,1); NTT(I,lim,1); 
        for(reg int i=0;i<lim;++i) H[i]=mul(H[i],I[i]); 
        NTT(H,lim,-1);
        for(reg int i=mid+1;i<=r;++i) F[i]=add(F[i],H[i-l-1]);
        return solve(mid+1,r);
    }
    

    uoj51

    考虑 (sqrt n) 不大,(2^{31}) 必然大于 (10^9)

    那么状态并不多,考虑记录每个状态的 (SG) 函数即可,使用记忆化搜索实现这个算法

    uoj52

    (mathrm{ codeforces}) 的题呀

    直接取阀值 (x=lfloorfrac{k}3 floor),在 (a,b,c) 三个数组里面找到这个位置上的数

    最小的那个数组里面前面的数不可能作为答案,删掉,迭代下去即可

    注意:如果把 ( exttt{kth.cpp}) 已经挪到桌面上了就用桌面上的写

    uoj53

    有一个显然的 (Theta(nklog(nk))) 的做法

    但是这个做法有很多冗余,也就是把所有的点都放到堆里面,其实我们只关注最小的

    关注到这个 (a,b,c) 的路径上的点可以被划分出来三个链,那么我们可以每次取最小的进行扩展

    这个过程是十分有技巧的,也就是记录链的首尾,然后进行最值分治

    形式化的而言,考虑当前链为 ((st,ed,pos))(pos) 表示链上最小权所在的点

    那么可以往堆里面扔一个 st,fa[pos],ask_chain(st,fa[pos]),和 unson(pos,ed),ed,ask_chain(unson(pos,ed),ed)

    其中 ( exttt{underson}) 表示该方向的儿子,ask_chain 表示链上最小值

    这样的话每次扩战展放到堆里面的数是常数级别的,就可过了

    拆链想到了,这个分治感觉有点意思,实现没有难度

    值得一提的是,这个题让我理解了 ( exttt{zkw线段树}),这样的收获十分有意义

    另外:记录本题卡空间的做法

    ((1)) 用手写堆代替 ( exttt{priority\_queue})

    ((2)) 记录堆里面的最大元素,( exttt{k<q.size()}) 那么就不再加入比最大还大的部分了

    ((3)) 重复使用数组,比如原来的 (sz) 数组后面就没用了

    ((4)) 结构体不要使用 ( exttt{node(st,ed,pos,val)}) 来赋初值,因为这个函数需要空间

    uoj207

    首先学习一下如何使用 ( exttt{LCT}) 维护虚子树信息

    值得一记的是 ( exttt{make\_root}) 的翻转时一定保证当前的 (x) 没有右儿子

    考虑给每个路径赋一个权值,加到首尾上面,然后对于每个路径,如果以 (x) 为根,(y) 的子树里面的权值和恰等于现在的路径权值和,那么满足条件

    考虑维护子树异或和,如果等于当前所有的路径异或和,那么正确

    这里用 (2^x) 次方对大质数的模当权值比较靠谱

    SDOI2018 旧试题

    先把式子推一推:

    [sum_{i=1}^A sum_{j=1}^B sum_{k=1}^C mu(i) mu(j) mu(k) sum_{mathrm{lcm(i,j)|x}}sum_{mathrm{lcm(j,k)|y}}sum_{mathrm{lcm(k,i)|z}}lfloor frac{A}x floorlfloor frac{B}y floorlfloor frac{C}z floor ]

    直接上连暴力都拿不到,关注到这个 (mu(i)) 有贡献的不多,看起来很像一个三元环计数的模型

    那么就可以对全不同,两个一样,全一样的三部分分开计数

    考虑系数中是轮换对称的三个独立函数,也就是

    [sum_{p|x} lfloor frac{val}x floor ]

    显然可以 (Theta(nln n)) 的时间复杂度之内求出来,那么就做完了

    ARC115 D. Odd Degree

    答案显然是把所有的联通块的答案搞个分治乘法

    因为奇偶性的缘故,有奇数度数的点一定只有偶数个,因为总度数是 (2n) 为偶数

    对于一个有偶数个度数为奇数的生成树,钦定哪个子集为奇数度数,剩下为偶数度数,都是可以从叶子开始向上剥来得到

    具体就是如果度数不为其儿子的情况剥完了,如果留下的边数是偶数,就断掉祖先边

    那么对于奇数个数为 (kin{even}) ,方案是 (inom nk)

    所以就做完了

    ARC115 E.LEQ and NEQ

    考虑容斥来做:总方案减掉有相邻且相同的段的方案

    那么有

    [dp[i][k]=sum_{j=1}^{i-1} dp_j[(k+i-j-1)] imes min_{j+1}^i{a_j},f[0][0]=1 ]

    第二维就直接实现了容斥,答案为 (f_{n,0}-f_{n,1})

    用单调栈优化 (dp) 并使用若干个前缀和数组分别维护其奇偶位置上的前缀和即可


    还有一种相对简单的转移,不需要第二维

    发现最后是 (f[n][0]-f[n][1]) 那么可以把对 (f[n][0]) 最后贡献的直接置负,最后加起来

    Codeforces1119H

    基础想法就是挨着个卷,优化考虑 (FWT) 的点值式子:

    [F_k[i]=(-1)^{cnt(i&a_k)}x+(-1)^{cnt(i&b_k)}y+(-1)^{cnt(i&c_k)}z ]

    那么不难发现这个 (x,y,z) 前面的系数只有 (8)

    一个 (trick) 是将 (b_k,c_k) 异或 (c_k) 最后的答案再异或回来所有的 (a_i)

    那么还有 (4) 种需要考虑的情况,利用四种情况的和为 (n),仅考虑 (F_k[b/c/(b mathrm{xor} c)[i]=0) 分别搞出来四个方程,手动解出来

    最后就剩下快速幂,(mathrm{IDWT}) 和下标反映射了

    loj6401

    因为是一个 (SAM) 题,那么考虑每个点上有多少字符串能被覆盖

    那么使用单调指针扫一下得到每个点的最长合法后缀的长度,然后放到 (SAM)

    最后在后缀树上扫一下,用每个点的儿子来更新 (fa) ,实现的时候注意两点:

    ((1)) 基数排序:for(reg int i=tot;i>=1;--i) id[ton[len[i]]--]=i;

    ((2)) 每个点的答案不仅要让 (max) 和长度取 (min) ,还得注意和 (0)(max)

    uoj60

    没有任何一种方案比 (4 imes 3 imes 3 imes 3 imes dots) 更大,直接输出即可

    loj6031

    先把这个 (mathrm{w(l,r)}) 看明白:是指整个子串而非这个区间里面的所有子串

    (S) 建自动机,得到每个点的 (mathrm{endpos}) 集合大小

    对于每个 (w) 放到上面跑匹配,能求出来 (w) 中以每个下标为结尾是 (S) 子串的最长后缀

    对于 ([a,b]) 中的每个区间,在后缀树上跑倍增,复杂度 (Theta(mathrm{qmlog n}))

    那么复杂度瓶颈在每个询问都得跑,考虑使用根号分治

    • 对于 (kge sqrt n) 的部分,询问不超过 (sqrt n) 个,直接照着上面的做法实现即可

    • 对于 (kle sqrt n) 的部分,对所有 (w_i) 对应的 (a_i,b_i) 离线之后扔一个莫队维护每个区间的出现次数

      求完了之后就直接 (Theta(k^2)) 做就行了

    复杂度想错了好久,其实是 (Theta(nk))

    DZY loves Chinese II

    先求出来一个原图的生成树,对于非树边,随机赋一个权值

    树边的权值就是非树边路径经过它的路径权值的异或和

    询问直接判断是不是线性不相关就行了

    正确性?

    如果分成两个联通块,中间树边有且仅有一条,且权值一定是同样连接两个点集的非树边的权值的异或和

    shallot

    线性基的删除是有通法的,但是这里考虑使用线段树分治,那么就分治就好了

  • 相关阅读:
    mysql之alter 字段的修改、添加、删除
    mysql之Percona-XtraDB-Cluster prohibits without an explicit primary key with pxc_strict_mode = ENFORCING or MASTER报错
    mysql之常用操作,创建库、表,删除库、表
    Spring Boot的消息之旅(一)
    Spring Boot的日志之旅(一)
    Spring Boot的缓存之旅(二)
    Spring Boot的缓存之旅(一)
    使用Druid数据库连接池
    Spring Boot的数据库之旅(二)
    Spring Boot的安全之旅(一)
  • 原文地址:https://www.cnblogs.com/yspm/p/14499350.html
Copyright © 2020-2023  润新知