zoukankan      html  css  js  c++  java
  • [正睿集训2021] 难题乱讲

    数数题

    题目描述

    ([0,n-1]) 这些正整数里选出恰好 (k) 个互不相同的数,使得它们的和是 (n) 的倍数,求方案数。

    (kleq 1000,nleq 1e9)

    解法

    真的被这道题锤爆了,还好我现在会做了

    首先这道题有两个限制:选出恰好 (k) 个数,和是 (n) 的倍数(互不相同太好做了),那么可以用 二元生成函数 来表示这两个限制,(x) 就解决和是 (n) 的倍数,(y) 就解决选出恰好 (k) 个数,那么写出我们的柿子,先说明一下 ([x^k]) 表示的是拿出生成函数第 (k) 项的系数,因为生成函数就相当于一个标记,但系数是有实际意义的:

    [[y^k]sum_{i=0}^infty[x^i]prod_{j=0}^{n-1}(1+x^jy)[n|i] ]

    现在介绍 单位根反演 ,原理就是 ( t FFT) 里面的那个求和引理:

    [[n|i]=sum_{j=0}^{n-1}w_{n}^{ij} ]

    这个东西的用法和莫比乌斯反演的用法差不多,遇到那个布尔表达式就干:

    [[y^k]frac{1}{n}sum_{i=0}^infty[x^i]prod_{j=0}^{n-1}(1+x^jy)sum_{k=0}^{n-1}w_{n}^{ik} ]

    下面的推柿子简直玄学,但是核心思想是:把二元生成函数转化成一元生成函数,也就是要消掉 (x) ,先改变枚举顺序:

    [[y^k]frac{1}{n}sum_{k=0}^{n-1}sum_{i=0}^infty[x^i]w_{n}^{ik}prod_{j=0}^{n-1}(1+x^jy) ]

    可能你现在还是看不出来,我再来操作一下:

    [[y^k]frac{1}{n}sum_{k=0}^{n-1}sum_{i=0}^infty[x^i](w_{n}^{k})^iprod_{j=0}^{n-1}(1+x^jy) ]

    那么 (x^i) 前面就自带了一个系数 ((w_n^k)^i),后面的那个求乘积是决定 (x) 的多项式的,我们可以把这个系数放在求乘积柿子的里面:

    [[y^k]frac{1}{n}sum_{k=0}^{n-1}sum_{i=0}^infty[x^i]prod_{j=0}^{n-1}(1+w_n^{jk}x^jy) ]

    然后这完完全全就只是求多项式 (x) 的系数和了,(x) 就可以丢掉了,这样我们就得到了一个一元生成函数:

    [[y^k]frac{1}{n}sum_{i=0}^{n-1}prod_{j=0}^{n-1}(1+w_n^{ij}y) ]

    下面的推柿子又是玄学东西了,设 (d=gcd(n,i)),我们要用它来构造互质的性质:

    [[y^k]frac{1}{n}sum_{i=0}^{n-1}Big(prod_{j=0}^{n/d-1}(1+w_{n/d}^{ij/d})Big)^d ]

    又要补充一个知识点了,考虑单位根有一个意义是 (x^n=1) 的解,那么根据因式定理,可以得到下面的柿子:

    [prod_{i=0}^{n-1}(x-w_n^i)=x^n-1 ]

    这个可以用来化简答案式:

    [prod_{i=0}^{n-1}(1+w_n^iy)=w_n^{n(n-1)/2}prod_{i=0}^{n-1}(y+w_n^i)=w_n^{n(n-1)/2}prod_{i=0}^{n-1}(y-w_n^i) ]

    (n) 是偶数的时候,(w_n^{n(n-1)/2}=-1) ,原式等于 (1-x^n),当 (n) 是奇数的时候,原式等于 (x^n-1)

    解释一下上面这东西怎么化出来的,首先我们把求乘第 (i) 项提出一个 (w_n^i) 出来,(1) 就变成了 (w_{n}^{n-i}),因为 (n-i) 同样取遍了 ([0,n-1]) 的所有整数,所以可以用 (i) 来代替,最后一步是把 (w_n^i) 变成 (-w_n^{i+frac{n}{2}}) 。把上面的柿子可以用来化简答案式,但是答案式多出了一个 (frac{i}{d}),注意到我们让它和 (frac{n}{d}) 互质了,所以它的 (j) 倍在模 (frac{n}{d}) 意义可以取遍 ([0,frac{n}{d}-1]),那么就可以直接看成 (j) 了,这样就可以化简答案式了:

    [[y^k]frac{1}{n}sum_{i=0}^{n-1}(1-y^{n/d})^d ]

    [[y^k]frac{1}{n}sum_{i=0}^{n-1}(y^{n/d}-1)^d ]

    上面两种选哪一个只取决于 (frac{n}{d}) 的奇偶性,然后用二项式定理就可以算第 (k) 项的系数了,我们枚举 (n) 的所有因数暴力统计即可,每个因数贡献 (varphi(n/d)) 次((i) 会取到这么多次),时间复杂度 (O(d(n)))

    字符串

    题目描述

    对于一个字符集 (Sigma) 上的字符串 (S) 和常数 (k),定义删去 (S) 中的 (k) 个相邻且相同的字符为一次操作,现字符集的大小 (|Sigma|=m),求 (Sigma) 上通过 (n) 次操作能够得到空串的字符串数量,答案对 (p) 取模。

    (n,kleq1e9,1leq m<p<1e5),保证 (p) 是质数。

    解法

    不会

    糖果

    题目描述

    (n) 个人和 (m) 种糖果,每种糖果分别有 (a_i) 个,每个人每种糖果至多吃一个,最多吃 (b_i) 种糖果。

    (q) 次修改,每次可以把某个 (a_i) 或者 (b_i) 加减 (1),每次修改后问是否存在方案使得糖果可以被分完。

    (n,m,qleq 3e5)

    解法

    贪心是可以的,但是不好维护,果断放弃。

    又要大开眼界了,首先建出这道题的网络流。这是一个满二分图,原点向左边连 (a_i) 的边,中间互相连 (1) 的边,汇点向右边连 (b_i) 的边。对这个图跑网络流然后验证最大流是否等于 (sum a_i) 即可。

    但是直接跑网络流肯定起飞了,我们考虑利用最大流(=)最小割的这个性质,去求原图的最小割。因为是个满二分图所以最小割可以求,设左边没被割的集合是 (S),右边没被割的集合是 (T),那么就要最小化下式:

    [|S| imes|T|+sum_{i otin S}a_i+sum_{i otin T}b_i ]

    如果我们固定了 (|S|),那么 (a) 那一项可以贪心地确定,(i) 如果不割会有 (|S|) 的贡献,如果割会有 (b_i) 的贡献,看哪个小就搞哪个就可以了。

    现在考虑这么维护上面的柿子,可以搞一个线段树维护所有 (|S|) 的值,那么答案就是全局最小值。如果修改 (a) 那么就是前缀加(/)减,如果修改 (b) 就是后缀加(/)减,但这样要保证相对顺序不变,如果有多个相同的数那么我们就修改最边边的数就不会影响相对顺序了。

    普通高中生

    题目都没看懂

    卖弱

    题目描述

    求有多少 (n) 个点 (n) 条边的有向图,每个点的入度出度都是 (1),并且如果 (i,j) 有一条边,必须要满足 (j)([i-a+1,i+n-a-1]) 中。

    (nleq1e6,aleq200),总共 (10) 组询问。

    解法

    (wzy) 割割:这个环特别不好看,所以我们来转化一下。

    首先有一个怎么也想不到的题意转化,有一个 (n imes n) 的网格,右上角挖掉一个长度为 (a) 的等腰直角三角形,左下角挖掉一个 (n-a) 的,剩下每行每列选且只选一个位置。这个网格 ((i,j)) 就表示 (i)(j) 有一条边,我画了一个比较养眼的图哦:

    如果没有右上角的那个三角形,那么方案数比较好算,下面梯形的方案数是 (a^{n-a}),上面矩形的方案数是 (a!),那么总方案数是 (a^{n-a}a!),限制是不能放右上角那个三角形,我们 把这个限制容斥掉 就可以了,枚举放在右上角三角形的数量。

    (dp[i][j]) 为边长为 (i) 的三角形放了 (j) 个点的方案数,那么有下转移:

    [dp[i][j]=dp[i-1][j]+dp[i-1][j-1] imes(i-j+1) ]

    枚举放在三角形里的数量 (j),那么乱放的方案数是 ((a-j)^{n-a}(a-j)!),相当于下面都挖掉了 (j) 列,那么容斥就很简单了。

    可爱

    题目描述

    总有一天我要改编一下这个题目描述

    给定一个字符串 (S),定义它的两个长度为 (m) 的子串相似,当且仅当这两个子串至多有一个字母不同。

    对于每个长度为 (m) 的子串,求有多少个子串和它相似。

    (|S|leq1e5)

    解法

    如果判断两个 (i,j) 开头的字符串 (m) 相似,当且仅当 (lcp(i,j)+lcs(i+n-1,j+n-1)geq m-1),先建出正串的 ( t Sam),在上面跑我们就知道了 (lcp) 是多少,同时也知道了 (lcs) 至少是多少,那么我们在反串的 (Sam) 上面倍增,找到最浅的祖先作为 (lcs),数一下子树内的点就行了。

    具体来说我们使用 ( t dsuspace onspace tree),维护一个树状数组求反串 ( t Sam) 的子树和就行了,小清新。

    担心

    题目描述

    共有 (n) 个人参加比赛,这 (n) 个人站成一排。比赛采取单挑制,每次等概率选取两个相邻的人进行单挑,胜者保留,败者淘汰。每个人的水平是不同的,第 (i) 个人的水平是 (a_i),如果一场比赛在水平分别为 (a,b) 的人之间进行,那么前者获胜概率是 (frac{a}{a+b}),后者获胜的概率是 (frac{b}{a+b}),直到最后只剩下一个人,求 (k) 留在最后的概率。

    (nleq 500)

    解法

    注意每次单挑只可能发生在相邻的人之间,所以我们使用区间 (dp)

    先写出暴力区间 (dp),设 (f(i,j,k)) 表示在区间 ([i,j]) 决斗完之后剩下 (k) 这个人的概率,那么转移需要枚举下一个区间,还要枚举胜者是谁,复杂度达到了 (O(n^5)),但是考虑到一个关系式:

    [f(i,j,k)=f(i,k,k) imes f(k,j,k) ]

    也就是这个人留下的概率等于他在两边区间分别获胜概率之积,低维 (dp) 总是比高位 (dp) 好优化一些 ,这个三维的状态是可以通过两个二维的状态表示出来的,所以我们改变状态定义,设 (l[i][j]) 表示区间 ([i,j]) 决斗完之后剩下 (i) 的概率,(r[i][j]) 表示区间 ([i,j]) 决斗完之后剩下 (j) 的概率。

    考虑怎样转移,其实要把 ([i,j]) 拆分成若干个区间,每个区间挑出一名胜者继续决斗,但是我们只需要考虑最后一段区间的胜者就行了,我们先枚举最后一段,再枚举它的胜利者是谁,还要算一下两个区间合并的概率,设一个区间的大小是 (a) 另一个是 (n-a),那么用概率乘以方案数就是 (frac{1}{(n-1)!} imes{n-2choose a-1}(a-1)!(n-a-1)!=frac{1}{n-1})

    [l(i,j)=frac{1}{j-i}sum_{k=i+1}^jl(i,k-1)sum_{p=k}^jr(k,p)l(p,j)frac{a_i}{a_i+a_p} ]

    这样不是特别好优化,我们考虑改变枚举顺序:

    [=frac{1}{j-i}sum_{p=k}^jl(p,j)frac{a_i}{a_i+a_p}sum_{k=i+1}^jr(k,p)l(i,k-1) ]

    后面的那个之和 (i,p) 有关,那么 (O(n^3)) 一定可以处理出来的,那么总时间复杂度 (O(n^3))

    string

    题目描述

    给定一个只包含字母 (A,B,C,D) 的字符串 (T)

    用串 (T) 构造一个新的串 (S) 的构造方法是进行多次操作,每次从 (T) 中选出一段的子串,加入到 (S) 的后面,显然对于一个串 (S),它的构造方法不只一种,定义 (S) 的构造代价为最少的操作次数。求一个长度为 (n) 的串最大的构造代价。

    (nleq1e18,|T|leq1e5),保证 (T) 含有所有四个字母。

    解法

    首先考虑如果确定了串 (S) 该怎么去算它的构造代价,从前往后计算,能匹配就匹配。

    (f(i)) 为长度为 (i) 的最大代价,但是这样不好转移。换一种定义方式,设 (f(i)) 为代价 (i) 的最大长度,由于是子串先建出 (S) 的后缀自动机,如果在后缀自动机上无法转移了那么就说明不能匹配了,重新定义 (f(x,i)) 为代价 (x) 的最大长度,并且最后因为匹配到了 (i) 字符而挂彩,所以可以这么转移:

    [f(x,i)=min_{k=0}^3f(x-1,k)+len(k,i) ]

    显然这个可以矩阵加速,然后我们用倍增代替二分即可,矩阵加速的复杂度是 (O(4^3log n)) 的。

    最后的问题是求 (len(i,j)),直接在后缀自动机上 ( t bfs) 即可。

    ARC080F

    题目描述

    有无穷个硬币,初始有 (n) 个正面向上,其余全部正面向下,你每次可以选择一个奇质数 (p),并将连续 (p) 个硬币都翻转。问最小操作次数使得所有硬币均正面向下。

    (nleq200)

    解法

    套路题了,可以考虑差分,设 (1) 表示正面向上的硬币,这样 (1) 的数量一定是偶数,问题变成了消去所有的 (1),消去是一个两两配对的过程,消去的代价之和他们的距离有关:

    • (|i-j|) 是奇质数,那么一步就可以消去。
    • (|i-j|) 是偶数,根据哥德巴赫猜想,可以两部消去。
    • (|i-j|) 是奇非质数,那么三步可以消去(拆出来 (3) 然后用两步)

    贪心地看,尽量多用第一种消法是最好的,所以可以把二分图建出来然后跑最大匹配。然后把没有匹配的数分奇偶用第二种消法,如果还有剩余的话就使用第三种,可以证明一定有解。

    机器人

    题目描述

    有一个 (n imes m) 的网格,一些网格上有机器人。机器人有四种朝向,它可以看到的范围是这样的:

    每个机器人最初都有一个朝向,机器人只能旋转 (90) 度,问最少旋转多少个机器人才能使所有机器人都不能互相看见,输出方案,机器人数量无限制。

    (nmleq 4e6)

    解法

    把图旋转 (45) 度之后视野变成了矩形(这一步是很常见的套路了)

    有一个很重要的结论:可以把左上右下,右上左下这两类分开考虑。比如下面介个例子:

    A   C
      /(!)
      B
       
        D
    

    如果 (BC) 冲突的话,我们考虑转 (B),那么 (B) 转到另一类的时候会不会因为和 (AD) 都冲突而无解呢?如果这样的话那么 (AD) 一定冲突,那么 (AD) 一定会有一个转到另一边。而且因为转到另一类是可以自选方向的,所以很多都会朝一个方向。

    考虑最后的状态(就拿左上右下来说吧),一定是有一个分界线,分界线左边都朝左上,分界线右边都朝右下。使用轮廓线 (dp),设 (f(i,j)) 表示轮廓线到了 ((i,j)) 的最小修改数,轮廓线每次可以向下或者向左走,向下走的时候计算一下修改的代价即可。

  • 相关阅读:
    关于万门大学api接口反爬措施的解决
    磁盘
    汇编实验九
    汇编语言第六章-包含多个段的程序
    汇编实验四
    汇编实验二
    汇编语言实验四
    汇编语言第四章——第一个程序
    汇编语言第三章——寄存器(内存访问)
    汇编语言第二张寄存器
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14409313.html
Copyright © 2011-2022 走看看