1355 斐波那契的最小公倍数

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1355
 
斐波那契数列定义如下:
 
F(0) = 0 F(1) = 1
F(n) = F(n-1) + F(n-2)
 
给出n个正整数a1, a2,...... an,求对应的斐波那契数的最小公倍数,由于数字很大,输出Mod 1000000007的结果即可。
例如:1 3 6 9, 对应的斐波那契数为:1 2 8 34, 他们的最小公倍数为136。
Input
第1行:1个数N,表示数字的数量(2 <= N <= 50000)。
第2 至 N + 1行:每行1个数,对应ai。(1 <= ai <= 1000000)。
Output
输出Lcm(F(a1), F(a2) ...... F(an)) Mod 1000000007的结果。
Input示例
4
1
3
6
9
Output示例
136

首先要用到一个定理 gcd(Fiba,Fibb)=Fibgcd(a,b) ,在这里证明一下好了。
根据递推式的定义 Fibn=Fibn1+Fibn2 显然有 gcd(Fibn,Fibn1)=1 和 Fibn+m=Fibn1Fibm+FibnFibm+1 ,那么就有 gcd(Fibn+m,Fibn)=gcd(Fibn1Fibm,Fibn)=gcd(Fibm,Fibn) ,下标上有辗转相减的形式,所以可以归纳证明 gcd(Fiba,Fibb)=Fibgcd(a,b) 。
然后再来考虑LCM和GCD之间的关系。
n=2时,有 lcm(Fiba,Fibb)=FibaFibbFibgcd(a,b) 。
n=3时,有 lcm(Fiba,Fibb,Fibc)=FibaFibbFibcFib1gcd(a,b)Fib1gcd(a,c)Fib1gcd(b,c)Fibgcd(a,b,c) ,这个结果可以类比通过子集的最小值得到全集最大值的容斥方法得到。
大概读到这里都发现可以 O(2n) 容斥了,但是此题 n50000 ,显然会超时啊,所以考虑优化。

细心的人可以发现 ai106 ,这么密集的数字进行容斥,所以自然而然的想到反演大法好咯,以下设 A=maxni=1ai 。

考虑 Fibai 对答案的贡献有点难度,但是我们可以反演之后将贡献定义到 Fibj{j|ai} 上,将反演的结果写出来可以发现,令 G(n)=Fibnd|n,d<nG(d)1 ,答案即 Ad=1[ni=1[d|ai]]G(d) ,就是说存在一个 ai 被 d 整除的话就考虑 d 的贡献,那么 G(d) 以及中间的真值表达式可以通过 O(AlogA) 的预处理得到,再 O(AlogA) 扫一遍用快速幂统计贡献即可,反演的主要作用是将贡献整理开,实现上可以先不做这个处理 G(d) 的操作,而是算出 Fibd 实际贡献的幂次,这样每个数来一遍快速幂就好。  by tls
posted @ 2016-11-17 01:43  BOSON+CODE  阅读(588)  评论(0编辑  收藏  举报