1355 斐波那契的最小公倍数
1355 斐波那契的最小公倍数
原题连接:
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1355
之前看唐老师题解学习的一个题目。顺便复习一下斐波那契数
今天想到一种相同结论。中间过程略微不一样的方法。
给定a1,a2,a3....ana_1,a_2,a_3....a_n
计算:LCM(Fa1,Fa2,...Fan)LCM(F_{a_1},F_{a_2},...F_{a_n})
这个题目其实用到了很多巧妙的结论。(需要你对斐波那契数的诸多性质有一定了解。
我们通常说的的fibfib数是指 F0=0 , F1=1 , n>0F_0=0\ ,\ F_1=1\ ,\ n>0
我们在快速计算modmod意义下的fibfib数事。通常会用下面递推矩阵:
[1110]n[FkFk−1]=[Fk+nFk+n−1]\left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right]^n\left[\begin{matrix}F_{k} \\F_{k-1}\end{matrix}\right]=\left[\begin{matrix}F_{k+n} \\F_{k+n-1}\end{matrix}\right]\\
我们看矩阵幂后里面的样子:
不需要计算。我们只需要观察。
[1110][acbd]=[a+cab+db]\left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right]\left[\begin{matrix}a & b \\c & d\end{matrix}\right]=\left[\begin{matrix}a+c & b+d \\a & b\end{matrix}\right]
从纵向看。每一项都是之前两项的的和。
那就有:
[1110]n=[Fn+1FnFnFn−1]\left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right]^n=\left[\begin{matrix}F_{n+1} & F_{n} \\F_{n} & F_{n-1}\end{matrix}\right]
那么就有:
[1110]n[1110]k=[Fn+1FnFnFn−1][Fk+1FkFkFk−1]\left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right]^n\left[\begin{matrix}1 & 1 \\1 & 0\end{matrix}\right]^k=\left[\begin{matrix}F_{n+1} & F_{n} \\F_{n} & F_{n-1}\end{matrix}\right]\left[\begin{matrix}F_{k+1} & F_{k} \\F_{k} & F_{k-1}\end{matrix}\right]
矩阵相乘之后你会发现,不需要数学归纳法。我们就有:
Fn+k=FnFk−1+Fn+1FkF_{n+k}=F_nF_{k-1}+F_{n+1}F_k
这个式子很重要。
首先
F2n=FnFn−1+Fn+1FnF_{2n}=F_nF_{n-1}+F_{n+1}F_n
这也就是说。F2nF_{2n}是FnF_n的倍数。
在有:
Fkn=F(k−1)n−1Fn+F(k−1)nFn+1F_{kn}=F_{(k-1)n-1}F_n+F_{(k-1)n}F_{n+1}
如果。F(k−1)nF_{(k-1)n}是FnF_n的倍数。那么意味着:
FknF_{kn}是FnF_n的倍数。
k=2k=2显然成立。那么意味着k=3,4,5,6..k=3,4,5,6..都成立
即,我们得到这样一个事实:FknF_{kn}是FnF_n的倍数。
那么就有:
Fn , Fk,他们都是Fgcd(n,k)的倍数F_n\ ,\ F_k,他们都是F_{gcd(n,k)}的倍数
所以:
gcd(Fn,Fk) 是 Fgcd(n,k)的倍数gcd(F_n,F_k)\ 是\ F_{gcd(n,k)}的倍数
我们有一个更确定的结论。
即:
gcd(Fn,Fk)=Fgcd(n,k)gcd(F_n,F_k)=F_{gcd(n,k)}
证明上面结论我们还需要一个结论:n>1n>1时 , 恒有FnF_n与Fn−1F_{n-1}互素。
那么(这里我们认为。n≥kn\geq k):
gcd(Fn,Fk)=gcd(Fk,Fn mod Fk)gcd(F_n,F_k)=gcd(F_k,F_n\ mod\ F_k)
其中:
Fn mod Fk=(Fn−kFk−1+Fn−k+1Fk) mod Fk=Fn−kFk−1 mod FkF_n\ mod \ F_k=(F_{n-k}F_{k-1}+F_{n-k+1}F_k)\ mod\ F_k\\=F_{n-k}F_{k-1}\ mod\ F_k
继续对 Fn−kF_{n-k}进行上述操作。我们得到:
Fn mod Fk=Fn mod kF⌊nk⌋k−1 mod FkF_n\ mod\ F_k=F_{n\ mod\ k}F_{k-1}^{\lfloor\frac{n}{k}\rfloor}\ mod\ F_k
所以就有:
gcd(Fn,Fk)=gcd(Fk,Fn mod kF⌊nk⌋k−1)gcd(F_n,F_k)=gcd(F_k,F_{n\ mod\ k}F_{k-1}^{\lfloor\frac{n}{k}\rfloor})
因为:Fk⊥Fk−1F_k\perp F_{k-1}
所以:
gcd(Fn,Fk)=gcd(Fk,Fn mod k)gcd(F_n,F_k)=gcd(F_k,F_{n\ mod\ k})
进而我们有:
gcd(Fn,Fk)=Fgcd(n,k)gcd(F_n,F_k)=F_{gcd(n,k)}
回到原问题:
lcm(Fn,Fk)=FnFkgcd(Fn,Fk)=FnFkFgcd(n,k)lcm(F_n,F_k)=\frac{F_nF_k}{gcd(F_n,F_k)}=\frac{F_nF_k}{F_{gcd(n,k)}}
可以肯定对是。上面对式子是不可用的。因为你会发现。他只适用于计算两个斐波那契数的最小公倍数。而不能计算一个斐波那契数和任意数字的最小公倍数。
因为斐波那契数是非常大的。答案要求对109+710^9+7取莫。
这就使得即使是朴素的最大公约数算法也是不可行的。
但最大公约数和最小公倍数都可以看作是质因数上的交集和并集。
有关集合之间的求解。多数与反演容斥有关。
试一试?
我们把数字看作素数的集合。
那么对于整数a,ba,b
则:
a⋂b=gcd(a,b)a⋃b=lcm(a,b)a\bigcap b=gcd(a,b)\\a\bigcup b=lcm(a,b)
a∈ba\in b就是a∣∣ba\big|b 此时,aa在bb中的补集合就是ba\frac{b}{a}
那么有:
answer=⋃i=1nFaianswer=\bigcup_{i=1}^nF_{a_i}
(很明显。这种表示得到的是一个多重集合。关于素因子的。而在这这种表示上。多重集合的集合元素个数的和等价于乘积。也就是说。|a|+|b|=|ab||a|+|b|=|ab| .一般性的容斥原理不在局限于元素个数的统计。而是集合对应的实值函数。这里。每一个素数的多重集合。都有且只对应一个整数。)
应用一般性的容斥原理:
⋃i=1nFai=∏i=1nFai∏1≤i<j≤nF−1gcd(ai,aj)∏1≤i<j<k≤nFgcd(ai,aj,ak)....\bigcup_{i=1}^nF_{a_i}=\prod_{i=1}^n F_{a_i}\prod_{1\leq i
上式子没有应用价值。但可以得到很多有用的信息。
对于答案的贡献。最终体现在每一个fibfib数上。
不妨设:
answer=∏i≥1Fh[i]ianswer=\prod_{i\geq 1}F_i^{h[i]}
专注于h[i]h[i]的计算。
记。在 a[]a[]中取kk个数。这kk个数的最大公约数等于nn的方案数量为:
pair(k,n)pair(k,n)
记。在 a[]a[]中取kk个数。这kk个数的最大公约数等于nn的倍数的方案数量为:
P(k,n)P(k,n)
则:
P(k,n)=∑n|dpair(k,d)P(k,n)=\sum_{n|d}pair(k,d)
记。a[]a[]中。nn的倍数的个数为cnt[n]cnt[n]
那么P(k,n)P(k,n)等效于在这cnt[n]cnt[n]个数中取kk个数的方案数
则:
P(k,n)=(cnt[n]k)P(k,n)=\binom{cnt[n]}{k}
应用经典反演有:
pair(k,n)=∑n|dμ(dn)P(k,d)pair(k,n)=\sum_{n|d}\mu\big(\frac{d}{n}\big)P(k,d)
求和得到h[n]:h[n]:
h[n]=∑k≥1(−1)k+1pair(k,n)=∑k≥1(−1)k+1∑n|dμ(dn)P(k,d)=∑k≥1∑n|dμ(dn)P(k,d)(−1)k+1=∑n|d∑k≥1μ(dn)P(k,d)(−1)k+1=∑n|dμ(dn)∑k≥1(cnt[d]k)(−1)k+1h[n]=\sum_{k\geq 1}(-1)^{k+1}pair(k,n)\\=\sum_{k\geq 1}(-1)^{k+1}\sum_{n|d}\mu\big(\frac{d}{n}\big)P(k,d)\\=\sum_{k\geq 1}\sum_{n|d}\mu\big(\frac{d}{n}\big)P(k,d)(-1)^{k+1}\\=\sum_{n|d}\sum_{k\geq 1}\mu\big(\frac{d}{n}\big)P(k,d)(-1)^{k+1}\\=\sum_{n|d}\mu\big(\frac{d}{n}\big)\sum_{k\geq 1}\binom{cnt[d]}{k}(-1)^{k+1}
因为:
−1∗(1−1)cnt[d]=∑k≥0(cnt[d]k)(−1)k+1-1*(1-1)^{cnt[d]}=\sum_{k\geq 0}\binom{cnt[d]}{k}(-1)^{k+1}
∑k≥1(cnt[d]k)(−1)k+1−1=0\sum_{k\geq 1}\binom{cnt[d]}{k}(-1)^{k+1}-1=0
所以:
h[n]=∑n|dμ(dn)[cnt[d]>0]h[n]=\sum_{n|d}\mu\big(\frac{d}{n}\big)\big[cnt[d]>0\big]
此刻已经很欣喜了。。。。(剩下的快速幂一波出答案。)
answer=∏i≥1Fh[i]ianswer=\prod_{i\geq1}F_i^{h[i]}
下面是AC代码
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define Ld(a) ((LL)a)
#define MAXN 1000005
using namespace std;
typedef long long LL;
const LL P=1e9+7;
int Ts[MAXN];
int mu[MAXN];
bool vis[MAXN];
bool G[MAXN];
int pw[MAXN];
void init(int n)
{for(int i=3;i<n;i++)for(int j=i;j<n;j+=i)if(vis[j]){G[i]=true;break;}
}
void getMu(int n)
{for(int i=1;i<=n;i++){int target= i==1?1:0;int delta= target-mu[i];mu[i]=delta;for(int j=i+i;j<=n;j+=i)mu[j]+=delta;}
}
void init2(LL n)
{for(LL i=3;i<n;i++)for(LL j=1;j*i<n;j++)if(G[i*j])pw[i]+=mu[j];
}
LL extd(LL a,LL b, LL &X, LL &Y)
{if(b==0){X=1;Y=0;return a;}else{LL r=extd(b,a%b,Y,X);Y-=X*(a/b);return r;}
}
LL pow(LL a,int b)
{if(b<0){LL y,Iva;extd(a,P,Iva,y);while(Iva<0)Iva+=P;a=Iva;b=-b;}LL temp=1;while(b){if(b&1) temp=(temp*a)%P;a=(a*a)%P;b>>=1;}return temp;
}
int main ()
{int n,a,A=1;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&a);if(a<3)continue;vis[a]=true;A=max(A,a);}init(A+1);getMu(A);init2(A+1);LL f1=1,f2=1,f3=2,ans=1;for(int i=3;i<=A;i++){if(pw[i]){ans=ans*pow(f3,pw[i]);ans%=P;}f1=f3;f3=(f3+f2)%P;f2=f1;}printf("%lld\n",ans);return 0;
}
1355 斐波那契的最小公倍数相关推荐
- 51nod 1355 斐波那契的最小公倍数
Upd2019.4.19 yy了一个新的做法 新的写法 之前的东西 链接:http://www.51nod.com/Challenge/Problem.html#!#problemId=1355 很神 ...
- [数论 斐波那契] 51nod1355. 斐波那契的最小公倍数
进入斐波那契领域的第一题- 不要脸地截图了Manchery的博客--原文在这里 #include <cstdio> #include <iostream> #include & ...
- 51nod1355:斐波那契的最小公倍数(数论)
题面 题意给出n个a,问LCM{ f(a) },f为斐波那契数. 知乎靠谱的题解 记住这两个路人性质就好 ①容斥求LCM lcm{S}=∏T⊆S,T≠∅gcd{T}(−1)|T|+1lcm{S}=∏T ...
- [51nod1355]斐波那契的最小公倍数
$\text{lcm}$不好处理,考虑转为$\gcd$,主要是因为$(f_n,f_m)=f_{(n,m)}$ $\text{lcm}$的本质是指数取$\max$,$\gcd$的本质是指数取$\min$ ...
- 求水仙花数 以及 最大公约数最小公倍数 以及 冒泡法 以及字母大小写的转换 以及简单选择排序法 以及斐波那契数列
什么是水仙花数呢? 假设一个数ABC是一个三位数. 水仙花数就是 A*A*A +B*B*B +C*C*C = ABC; 水仙花的具体代码. 接着是最大公约数以及最小公倍数 如果两个数是ab,最大公约数 ...
- 51nod1355-斐波那契的最小公倍数【min-max容斥】
正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1355 题目大意 定义fif_ifi表示斐波那契的第iii项,给出一个大 ...
- python斐波那契数列30_python的30个骚操作
1.冒泡排序 2.计算x的n次方的方法 3.计算a*a + b*b + c*c + -- 4.计算阶乘 n! 5.列出当前目录下的所有文件和目录名 6.把一个list中所有的字符串变成小写: 7.输出 ...
- 51Nod-1355-斐波那契的最小公倍数
ACM模版 描述 题解 找到一个不错的知乎链接,对这个问题有详细的回答,可以仔细看看 张一钊 大佬的讲解. <怎样求出K个斐波那契数的最小公倍数?> 很详细的讲解,Orz~~~除了膜拜,我 ...
- 大数斐波那契数列+取余
斐波那契序列 集锦 (转) [定理1] 标准Fibonacci序列(即第0项为0,第1项为1的序列)当N大于1时,一定有f(N)和f(N-1)互质 其实,结合"互质"的定义,和一个 ...
最新文章
- java 线程交替输出,[java]java经典问题之线程交替打印数字
- java栈的实现_栈的实现(Java)
- Java 8————Collectors中的中的joining 方法和mapping方法
- C语言和设计模式(抽象工厂模式)
- mac电脑的磁盘空间变得越来越小
- QT编程-----------------窗口部件的使用(QWidget和QDialog)
- Hadoop学习笔记三
- 【考研计算机网络】 冲刺笔记
- 树莓派I2C通过Shell操作FDC2214
- cad修改快捷键_【收藏】史上最齐全的CAD大全
- PHP手册-use关键字
- python 中的switch
- 三年磨一剑:蚂蚁金服的研发效能洞察实践
- image标签不显示照片img标签能显示
- 禁用开启笔记本自带键盘
- Unity VFX学习系列 —— 效果制作(烟花)
- 《Unity编辑器》截图记录Unity好看的编辑器样式
- IP地址IP网段合并
- oracle时间戳概念,Oracle时间戳数据types
- D-Bus:busctl的使用