A. 模式
计算机学院是6系,软件学院是21系,对于输入的学号只需要判断⌊id10000⌋是多少即可。
B. 并联变阻器
题意即统计满足a,b≤N且aba+b是整数的二元组(a,b)的个数,条件也即a,b≤N且(a+b)|ab。
令r=gcd(a,b),则有gcd(ar,br)=1,再令a=rx,b=ry,那么(a+b)|ab 可以表示为r(x+y)|r2xy,也就是(x+y)|rxy。
由于x与y互质,所以gcd(x+y,x)=gcd(x+y,y)=gcd(x,y)=1,(x+y)与x,y也是互质的,则必然有(x+y)|r。
令r=k(x+y),则a=kx(x+y),b=ky(x+y),可以发现a,b≤N对应着x,y≤N−−√,只需要枚举不超过N−−√的互质数对(x,y),即可计算出对应的每一组解,这样做的时间复杂度是O(N−−√2)=O(N)的,其中求最大公约数的部分可以通过预处理达到O(1)。
注意到本题的数据组数较大,单组数据使用O(N)算法也会超时,但是枚举所有解的时候也确定了这组解是属于N≥max(a,b)的所有N,所以将这组(a,b)统计到对应的max(a,b),再求一遍前缀和即可得到所有答案,预处理复杂度O(N),单点查询O(1)。
C. 抽奖箱
题意可以稍作简化,考虑成n次抽奖,每次只有m位老师和ai位学生,需要求抽到k位老师时,在这k位学生之前的同学平均情况下有多少位。不同班的学生之间互相不影响。
注意到样例解释里不同情况下的概率是不一样的,不便于分析,可以将抽取的序列补全成抽完(m+ai)个结果的一个排列,这样每个排列的概率都是1(m+ai)!。
一个直观的结论是,可以认为学生是等概率分布在老师之间的,即任意两个相邻的老师之间平均情况下有相同数量的学生,那么m位老师将序列划分成(m+1)个段,每段平均情况下有aim+1个学生,所求即前k个段里平均情况下的学生个数,也就是ai⋅km+1。如果理解了数学期望的线性性,应该会很快得到这个结论。详细的证明可以参考超几何分布的期望。
D. 最大公约数
最大公约数满足结合律,所以题目所说相等的gcd就是原数列的gcd,不妨设为d。
设f[i]为前i个数能分的最大段数,枚举最后一个段是[j+1,i],则有gcdik=j+1ak=d,而f[i]=maxf[j]+1。如果j不存在,可以认为f[i]是不合法的部分,令f[i]=0即可。
不难证明满足条件的j是一段前缀区间,而且f[i]是单调的,所以最大的f[j]一定是尽量靠右的,可以直接找到这个j来对f[i]更新答案。
区间gcd可以预处理ST表得到,或者顺着推以每个点结尾的区间gcd即可,可以证明以每个点结尾的区间gcd的值个数是不超过logn个的,所以整体的复杂度是O(nlog2n)。
E. 矩阵
设 Xi代表第i行所减少的权值,设 Yj代表第j 列所增加的权值。
则 Cij=Yj−Xi, 推出 Xi+Cij≤Yj 和 Yj−Cij≤Xi,根据差分关系建边。原问题就变成:是否所有的环权值都为0。n+m 只有 100,所以floyd和spfa找环什么的都可以过。
PS:没想到大部分人都用高斯消元过掉了。
F. 序列
对于一个固定的排列p,权值为 1+∑n−1i=1[pi>pi+1]。所以相邻两个数字,如果前面数字大于后面数字则对答案贡献1。
公式:(n2)(n−11)⋅(n−2)!+n!=(n+1)!2。
G. 就是这么巧
这题的结论: 1.对于符合条件的(a,b),a2+b2ab+1是一个完全平方数
2.对于给定的n,a2+b2ab+1=n2的所有解是数列a1=n,a2=n3,ai=n2ai−1−ai−2,i>2中的相邻两项。
证明:
- 结论1:
- 结论2:参考结论1的证明
令:a2+b2ab+1=k>0,a≥b,并移项化简得:a2−kb⋅a+b2−k=0。
对于给定的k,我们将a,b的范围从正整数扩大为整数。那么a,b不会异号(否则a2−kb⋅a+b2−k≥a2+k+b2−k>0,矛盾),即ab≥0。
已知a是一元二次方程x2−kb⋅x+b2−k=0的一个解,设另一个解为a′,根据韦达定理:
公式a+a′=kb就是An−1+An+1=kAn。
就是说任意给定一组解(b,a),我们可以求出另一组解(a′,b),且a′<b≤a,继续迭代可以得到一个无穷数列{ Ai},(Ai,Ai+1)都是解。
当k>1时,这个数列是递增的;并且关于原点对称,因为(−a,−b)也是一组是解;并且0是数列中的某一项(否则必然存在Ai<0<Ai+1);从而对于给定的k,所有的解都在这个数列中。
H. 高中数学题
题目给出了一个仅含an、Sn的公式,根据高中数学知识,很容易解出它的通项:an=2n+1
我们要求的是这个序列的前n项异或和
对于自然数的前n项异或和Xn,有如下规律:
本题中的序列就是自然数序列左移一位,再加1得到的
因此先将自然数序列的前n项异或和算出,之后将其左移一位再单独考虑最后一位的情况就好了。
I. 神奇宝贝大师
首先很重要的一点,我们可以发现X方向位置的选择和Y方向位置的选择是相互独立的。如果能想到这点这题就非常非常简单了。
假设我们最后答案是(ansx, ansy),我们只要独立的找到ansx和ansy就好了。 而只考虑X方向或者Y方向的话,就把原题转换成了一维的问题:给一个数组a,找一个位置x使得∑ai⋅|i−x|最小。
而这个一维的问题就很好解决了。可以O(n)扫一遍维护一下前后的距离暴力统计取min,或者直接找中间位置。而这个题更加简单一些,2000的数据范围直接O(n2)暴力枚举都是可以的。
J. 铅导体
这个题目的操作是在原图的每条边上加上一个dt,我们可以发现,最终影响答案的是每条路径的边数。我们不妨把所有从S到T的路径表示为A+B⋅dt的形式,A代表原图该路径的长度,B代表该路径的边数。
而A+B⋅dt是一束直线,且我们显然可以将其优化为n条直线(对每个B,取最小的A)。那么对于每个询问dt,答案就是这一束直线在x=dt处的最小值。我们可以处理出一个最多由n条边组成的下凸壳,对每个询问二分查找其所在的凸壳上的段,即可直接求出答案。
由于前面求n条直线的复杂度为O(nm),求下凸壳的复杂度为O(n),回答询问的复杂度为O(qlogn),所以总的复杂度为O(nm+qlogn)。题目中的nm比较大,但是实际上在图中跑的速度还是很快的。另外,由于数据未进行特别的构造,导致暴力处理n条直线,并且询问时枚举n条直线计算最值的算法也通过了此题。
K. 危险密码
两个字符串的编辑距离即一个串通过添加、删除、修改三种操作变成另外一个串的最少操作次数。
对于一个字符串s,设它的长度为n,可以发现h=(∑n−1i=0ai⋅Kn−1−i)modM,枚举添加、删除、修改的一个字符串,计算新串的h′即可。
对于修改第i(0≤i<n)个位置为c,h′=h+(c−ai)⋅Kn−1−i。
对于添加和删除需要一些额外的信息,令prei表示字符串s的前i个字符表示的h值,pren即s的h,再令sufi=pren−prei⋅Kn−i+1。
对于在第i(0≤i≤n)个字符前添加一个c,h′=prei⋅Kn−i+1+c⋅Kn−i+sufi+1。
对于删除第i(0≤i<n)个字符,h′=prei−1⋅Kn−i+sufi+1。
L. 偶回文串
题意即统计有多少个连续的子串满足在它里面出现的字符都出现了偶数次,满足这样条件的子串总能通过重排字符的顺序得到一个偶回文串。
任意一个子串里某个字符的出现次数可以被表示成两个前缀字符串里出现次数的差,例如abbababbabbab的子串ababba,就可以表示成abbababba和abb的差,如果这两个前缀串里任意一个字符出现的次数在模2意义下是相等的,那么他们的差对应的子串就是一个合法的解。 以第i个字符结尾的前缀串和以第i+1个字符结尾的前缀串只差一个字符,可以通过线性递推得到所有的前缀串的26个字符出现次数的奇偶性,可以发现每个前缀串对应26个不是0就是1的数字,可以将其压缩成一个二进制数字si,si的第k位对应第k个字符出现次数的奇偶性,添加一个字符可以利用二进制不进位加法,其中二进制不进位加法可以用异或(xor)来表示。
算出所有的si之后,可以通过C++ STL map或手写散列函数统计相同的si出现个数,也可以直接进行排序将相同的si排到一起。不妨设有a个si是相等的,那么它们可以对应a⋅(a−1)2个子串,分别考虑每组相等的si,将贡献累加即可。时间复杂度O(nlogn)。
M. 我是鱼
一个数和自己异或(⊕)结果为0,所以如果只有一个数是奇数全部异或起来就能得到结果,如果有两个数是奇数,假设为a,b,把所有数异或起来的结果等于a⊕b,设c=a⊕b,则c≠0,c的二进制表示中必有某一位为1,假设为第x位,那么将所有第x位为0的异或起来,所有为1的异或起来就能得到a,b。