A:将1~n放入n个位置,问有多少种方案使得按照题目给出的寻找m的二分程序最终找到的位置是k
可以模拟题目的二分程序,最后的位置是k,那么有log个位置的值和m的大小关系就确定了,算先放这些位置的方案数,剩下的位置放什么都行,有(n-log)!种方案
因为n的值很大,所以算阶乘可以分段打表
表的每段长度K,
O(logn+n/K+K)
B:给出n个数字,问用这n个数字组成的序列有多少种满足相邻两项差的绝对值小于1
首先排序,如果值不是连续的就一定无解
然后DP,将这些数字从小到大,相同的数字一起插入,因为每个数字能插入的位置只能是两个上个数字的间隙,或者边缘且旁边是上个数字,f[i][j][k]表示插入到第i个数字,前一个数字两两有j个空隙,边缘有k个上个数字(k=0~2),合法的方案数
设有m种数字,每种数字大小c
O(m∗c2)
C:给出A序列B序列,问有多少个区间[l,r]满足max(a[l~r])= max(b[l~r])
对于A、B序列的每个数,求出他的左边和右边第一个比他大的数的位置:
apre[i],asuf[i],bpre[i],bsuf[i](apre,asuf,bpre,bsuf都是用来处理边界的)
只考虑A序列,对于以a[i]为最大值的区间[l,r],一定有
l,r∈[apre[i]+1,asuf[i]−1]
,
这时要求max(b[l~r])=a[i],所以还要记录对于每个位置i,满足b[j]=a[i],j<=i时的j最大值,记作pre[i],j>=i时j的最小值的suf[j],
这时l~r至少包含pre[i],suf[i]中的一个才能保证max(b[l~r])=a[i],同时两个序列都不能有大于a[i]的数,根据左右第一个比他大的位置找l,r的取值范围计算
细节有点多
另外,对于序列中相同的数要特殊处理,因为如果a[i]=a[j],i< j ,且i+1~j-1的最大值< a[i],这时会出现i,j的apre,asuf相同的情况,b序列没什么限制的话,有可能导致一些区间算重复,我处理的方法是找右边时,相同的数视为比a[i]大的数,找左边时,相同的数视为比a[i]小的数
O(n)
D:
定义f(T)为集合T的大小的k次幂,对于有n个元素的集合的所有子集T,
计算
(f(T)−f(S−T))2的方差∗2n
,对质数p取模(p<=
106
)
易知平均数为0
所以就是计算
∑T∈S(f(T)−f(S−T))2(Mod p)
大小一样的集合可以一起算,令
g(x)=(xk−(n−x)k)2
所以化简柿子成
∑ni=0Cin∗g(i)
套个Lucas,若n在p进制下表示为
n1,n2,n3,n4.....nm
因为当j>i时,
Cji=0
,所以柿子变成了
∑n1i1=1Ci1n1∑n2i2=1Ci2n2....∑nmim=1Cimnmg(im)
,后面的东西和前面无关,所以对前面求和,又因为
∑n1i1=1Ci1n1∑n2i2=1Ci2n2....∑nmim=1Cimnm=∑Cin=2n
所以柿子成了
2⌊np⌋Modp−1∑nmim=1Cimnmg(im)
⌊np⌋Mod(p−1)=(nModp∗(p−1))/p
然后就可以算了
因为k已知,
nk
是个积性函数,所以可以线性筛
O(p)
E:没做
F:听说是带花树开花(一般图最大权匹配),没做