[肝学习资料]构造题

来源:互联网 发布:shack it 编辑:程序博客网 时间:2024/06/11 01:16

Hack it CF468C

定义f(x)表示x的数字和,给定a请输出一组l,r,使[l,r]的f值和为a的倍数 。

对于x考虑10^y>x,那么显然f(x+10^y)-f(x)=1
设solve(l,r)表示[l,r]的答案,显然有solve(2,10^18+1)-solve(1,10^18)=1
相当于少了个f(1)多了个f(10^18+1),根据上面的结论差为1。
推广到一搬solve(x+1,10^18+x)-solve(1,10^18)=x
于是我们可以计算[1,10^18]的答案,设为s。
那么走a-s步即可。

至于如何计算solve(1,10^18),可以考虑计算每个数字的出现次数。

Prefix Product Sequence

一个长度为n的数组a的前缀积数组为b,其中bi是a前i项的积模n。
请给出一个n的排列作为a数组使其前缀积数组中[0,n-1]均出现过。

什么时候有解?
先看结论:
n=1显然就是1。
当n为大于4的合数时,无解。
而n=4是答案是[1,3,2,4]。
为何会无解呢?
首先bn肯定是n!模n,那么bn就是0。
0已经出现一次了,因此bn-1一定不是0。
同样显然an=n,因为放前面会导致0直接在前面出现。
而n是合数,所以可以写成n=pq,pq均小于n。
如果p!=q,显然都被(n-1)!包含了p、q两项,那么就为0了。
如果p=q,因为n>4的缘故,2p<n,那么(n-1)!至少有两项p,也为0了。

考虑n是质数的情况,我们如何构造解。
先看结论:
ai=i1i
这个显然构造出的b数组合法,而且因为n为质数,每个i都能找到逆元。
a数组合法吗?探究一下ai=aj的条件,发现是i=j,因此a就是一个n的排列。

Double Knapsack CF618F

现有两个多重集A和B,包含的数的范围是[1,n]的正整数。在A与B中分别选出一个非空子集(也是多重集)使这两个子集中元素和相同。

把集合中的元素弄到一个序列中。于是我们现在有序列A和B,处理前缀和SA和SB。
对于每一个SAi(0<=i<=n),我们都可以找到一个最大的j使得SBj<=SAi,容易知道SAi-SBj

Sum ONTAK 2014

构造一个B集合使得A集合内每个元素都是B集合一个子集的和,且B集合的所有子集和互不相同。

构造过程:
1、如果A集合存在奇数,找到最小奇数k,并将所有其他奇数减去k,然后删去k。
2、将A集合所有数除以2并去重。
3、递归下去。
A集合为空集时即可返回。
递归回来
1、将B集合所有数乘以2
2、如果该层删除了一个k,往B集合加入一个k。

为什么这么构造是对的?
假设A集合有一个数a,那么一层一层下去a=k1*2^p1+k2*2^p2……
k1、k2等都是在某一层被删除的数,而k1和k2显然会被加入到B集合,并且在返回到这一层时已经变成了k1*2^p1、k2*2^p2等。
因此A集合所有数都是B集合的子集和。

接着证明这样做B集合的所有子集和两两不同。
首先每一层的B集合一定都满足这个条件,递归边界时的空集肯定满足。
对于每一层,如果新加入了一个k,这个k是奇数,而此时B集合里其他数一定是偶数,新造成的子集和均为奇数,不与原来的子集和相同,又原来的子集和不同,所以都加上一个奇数后仍然两两不同,算上旧子集和两两不同,得到的新的B集合的子集和是两两不同的。

未完待续

0 0