zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    同余 扩展欧几里得
    185. [USACO Oct08] 挖水井
    Dijkstra算法
    Floyed算法
    codves——1079 回家
    codves——1021 玛丽卡
    codves——5960 信使
    计算几何基础
    【正睿oi省选十连测】第一场
    [APIO2012]守卫
  • 原文地址:https://www.cnblogs.com/boson-is-god/p/6072271.html
Copyright © 2011-2022 走看看