第一题:
题目大意:
数列a[0]=a[1]=1, a[n]=a[n-2]*a[n-1]*n,求a[n]的因子个数 mod 1000000007. n<=1000000
解题过程:
1.递推式还真没想出来,就记录每个a[i]的分解质因数的结果,然后转移质因子的个数。可以拿到30分。
2.思路:计算a[i]的时候,a[i]=a[i-2]*a[i-1]*i. 追踪这个i,它到a[i+1]里的时候是一个i,到a[i+2]里的时候是2个i,到a[i+3]里的时候是3个i,到a[i+4]里的时候是5个i,所以可以发现i到a[n]里的时候就有F[n-i+1]个i.(F[i]表示斐波那契数列第i项).
3.根据这个思路就可以来做了,首先很容易想到可以把1~n都分解质因数就可以得出a[n]中各个质因子的个数了,但是对于100w的数据显然是跑不出来的。时间复杂度是O(n*sqrt(n))
4.既然1~n都要分解质因数,那么不妨直接仿照筛法来做。举个例子:对于质数3,可以筛到3,6,9,12... 3,6,12里都有1个质因子3,那么a[n]中的质因子3的个数就可以加上F[n-3+1],F[n-6+1],F[N-12+1].. 而对于9,他有2个质因子3,那么a[n]中的质因子3的个数就可以加上F[n-9+1]*2. 也就是k中有多少个质因子x,就让a[n]质因子x的个数加上多少个F[n-k+1].时间复杂度成功降为O(n*log2n). 但是还是跑不出100w的数据。
5.更进一步优化可以到O(n). 对于数k,假设它有一个质因子p,显然a[n]中的p的个数要加上F[n-k+1].那么加起来之后就先不要管它。但是k/p的每个质因数在a[n]中也要出现F[n-k+1],被我们忽略掉了(实际上是把它放到分解k/p的时候来算),所以当分解真正的k/p的时候,它的每个质因子在a[n]中本来是要出现F[n-k/p+1]次的,但是之前还有一个被我们丢掉的k/p,要出现F[n-k+1]次,所以当我们分解真正的k/p的时候,把它在a[n]中出现的次数当做F[n-k/p+1]+F[n-k+1]次就可以了。
因此在分解k的时候,只要计算最小的质因子p(其实可以任意一个质因数),然后F[n-k/p+1]=F[n-k/p+1]+F[n-k+1]. 非常巧妙. 至于为什么要最小的质因子p,是因为可以用O(n)的筛法处理出每个数最小的质因数。
第二题:
题目大意:
解同余方程组
x mod m1=a1
x mod m2=a2
...
x mod mn=an
解题过程:
1.这题数据真良心,直接暴力枚举+卡时骗到了60分。
2.AC算法和扩展欧几里得有关,我直接补充到之前的关于扩展欧几里得的文章里了。
http://www.cnblogs.com/vb4896/p/4009181.html
第三题:
题目大意:
在三维空间里从(0,0,0)出发,要求走n步回到原地.第k步可以让x,y,z坐标的任意一个+-k,然后还有一些障碍点不能通过,也不能走走过的点,求所有方案。 n<=12.
解题过程:
1.看到n的范围这么小八成就是搜索了,先打了个最裸的搜索,发现竟然很快可以跑出10以内的数据,对于11和12就不大行了。
2.由于第k步只能让一个坐标+k,很多情况下都是永远走不到原点的. 假设是在第k步,当前的坐标是(x,y,z).之后肯定要让xyz都变成0, 那么不考虑障碍什么的,在最理想的状况下,x,y,z在后面的第k+1,k+2...n步中,要么+t,要么-t,要么不变.所以可以倒着dfs预处理出一个数组d[i][j],表示在第i,i+1,i+2..n步里能否达到j. 就可以拿来剪枝了:
d[k+1][-x]==false || d[k+1][-y]==false || d[k+1][-z]==false 的时候直接return.
这样对于n=12且没有任何障碍点的数据都能很快出解。