PKUSC TEST 2:Math teacher's homework
原题链接:http://poj.grids.cn/practice/4024/
题目大意:给定一个有n(n≤50)个整数的数列m(mi≤maxlongint),求满足XOR{xi, 1≤i≤n}=k的数列x的个数对1000000003取模的值,对于任意的1≤i≤n,0≤xi≤mi。
考试的时候没能做出来,我非常的不爽……其实这个题不是那么难……
首先我们得分析这个题更加深层次的性质。
首先,由于是有关于异或的问题,显然各个位之间是不相关的。大的思路还是按位来做。
为了方便起见,我们将原题的条件修改为0≤xi<mi。也就是原来的m数列中每一项都加1。
如果xi<mi的话,一定满足这样一个性质,那就是xi和mi的最高的若干位是一样的,在之后的一位上,mi为1,而xi为0。这之后xi的各个位就随便取了。
这个性质备用,我们继续分析这么一个东西:有一个n个数的数列k,对于任意的1≤i≤n满足ki∈{0, 1}。如果XOR{ki, 1≤i≤n}=u,且u∈{0, 1},求满足条件的k数列的数目。
这个的答案显然是2^(n - 1)。我们先随便取n - 1个数,最后一个数显然有且只有一种取法使得条件满足。
现在我们继续增加一个条件。如果对于一个整数0≤p≤n,k数列的前p项都是确定的。这时的答案是多少?
这就不用说了。如果p≠n,显然是2^(n - p - 1);如果p=n,就得看条件满足与否了。
由以上的两个分析我们可以想到这个题的一个初步做法。
我们不妨想象这个题实际上是要求一个合法的01矩阵的数目,其中每一行所表示的数小于一个定值,而每一列的数字异或起来又等于一个定值。由前面的两个分析,我们可以得到解的形态的模式图,如下图所示(当然了,这个矩阵应该有32列):
深蓝色的部分表示和mi的这一位一样。绿色部分表示mi的这一位是1,而这里是0的一位,橘黄色的部分表示不可以被随便确定的位,而浅蓝色部分表示可以被随便确定的位。这种情况可能成为解的充要条件是没有橘黄色格子的列中的数异或起来和答案的这几位一样。答案显然是2^(浅蓝色格子数)。
并且,一列中显然要么没有橘黄色格子,要么只有一个。我们规定橘黄色格子是该列第一个不是深蓝色和绿色的格子。由分析一,蓝色部分是连续的,并且一定在前面。所以说,有橘黄色格子的列也是连续的,而且一定在后面。
由于行的情况比较单纯,我们的思路就是按行DP。用F[i][j]表示前i行的状况已经确定,并且前j列没有橘黄色格子的方案数。我们先无视每一列异或起来要等于定值的限制。
我们用下面这张图说事:
比如说,我们现在要确定的是第六行的状态。那么实际上就是确定绿色格子在哪一列。而这一列后面的诸列中如果有没有橘黄色格子的,就需要在这一列中添加橘黄色格子。然后剩下的格子就可以随便确定了。在上面的例子中,我们从F[5][4]转移到了F[6][2],并且,由于有5个浅蓝色格子,实际上我们要在F[6][2]中加上F[5][4] * 2^5。
用这种方式我们就可以把所有可能的模式和它们的解数一直累加到最后一行。
一直搞到最后一行,我们发现一个新的问题——现在我们不能无视每一列的异或值为定值这一限制了。而前面说过,有解的充要条件就是前几个没有橘黄色格子的列,里面的定值的异或为答案的前几位。我们发现一直到倒数第二列,矩阵里面的所有数都和m数列里面的一样,而倒数第一列就不一样,有了绿色格子。为了统计合法的模式数,我们增加一维,用G[i][j][k]表示F[i][j]中的所有方案中,第j列的异或值为k的方案数,k∈{0, 1}。这样,最后一行计算完毕之后,我们就可以得到答案数了。
时间复杂度……从渐进意义上是O(N),因为实际上是O(32*32*2*N)……什么的。
代码如下:看代码
本文最近访客