怎樣求出K個斐波那契數的最小公倍數?

k&<=50000,f(i)中i&<=1e6.結果mod 1e9+7

幫助同學提問。


這個題前天鄙省省隊集訓剛做過,數據範圍完全相同。這個題本身就是一個出過很多很多次的原題。

首先有結論 gcd(f_n,f_m)=f_{gcd(n,m)}。這個只需要注意到 gcd(f_n,f_m)=gcd(f_n,f_{n-m}) 即可。

然後關於多個數的 	ext{lcm},有許多同學認為 	ext{lcm}{S}=displaystylefrac{prod S}{gcd{S}},這顯然是不對的。正確的結論應該是 	ext{lcm}{S}=displaystyleprod_{Tsubseteq S,T
e ,emptyset} gcd{T}^{(-1)^{|T|+1}}。這個結論可以對 	ext{lcm} 的每個質因子的冪進行最大最小值容斥得出。

對這個題應用這個結論,可以得到:

egin{aligned}	ext{lcm}{f_S}=prod_{Tsubseteq S,T
e ,emptyset} gcd{f_T}^{(-1)^{|T|+1}}\=prod_{Tsubseteq S,T
e ,emptyset} f_{gcd{T}}^{phantom{gcd{T}}(-1)^{|T|+1}}end{aligned}

然後我們構造數列 {g_n},使其滿足 f_n=prod_{dmid n}g_d,則有

egin{aligned}	ext{lcm}{f_S}=prod_{Tsubseteq S,T
e ,emptyset} {left(prod_{dmidgcd{T}}g_d
ight)}^{(-1)^{|T|+1}}\ =prod_{d}g_d^{sum_{Tsubseteq S,T
e ,emptyset,d|T}(-1)^{|T|+1}} end{aligned}

考慮 g_d 指數的意義,可以得到

displaystylesum_{Tsubseteq S,T
e ,emptyset,d|T}(-1)^{|T|+1}= egin{cases} 1  left|{amid ain S,d|a}
ight|>0\ 0  	ext{otherwise} end{cases}

因此有

	ext{lcm}{f_S}=displaystyleprod_{exists ain S, dmid a}g_d

通過此式可以在 O(nlog n) 時間內計算答案(n=max{S})。

有人問 g_n 怎麼算,把定義中除了 g_n 的項都移到另一邊就能得到 g_n=f_ncdotleft(prod_{dmid n,d
e n}g_d
ight)^{-1},愉快的按這個式子遞推就可以了。


頂一下 @張一釗 的答案。這個題目最早是在14年HackerRank的一次比賽中看到,原題範圍N &<= 1E9,K&<= 100。解法是一樣的。我做過比賽之後,覺得這個Idea很新穎,但解法不夠優雅,便修改了數據範圍,N &<= 1E6,K &<= 50000。於是有了一個與K無關的解法(nlogn)。預處理逆元後,用篩法就搞定了(不到30行代碼)。個人認為這個數據範圍的修改提升了題目的質量。雖然現在已淪為路人題,但當年這題還是很有意思的。

Fib的最小公倍數 - 51Nod ,給大家一個提交地址。


是不是這個題啊

我記得O( nlogn )搞一波就完了

=@@problem.Title 問題 - 51Nod


在LRJ的黑書上面有個結論,是 gcd(fib(a),fib(b))=fib(gcd(a,b))

這個結論是可以直接推廣到多個元素的,所以到這裡已經能夠快速求得 gcd(fib(a,b))

然後取模環境的除法記得用求逆的方式

//之前想法有問題,改成了現在的版本

這個gcd啊和lcm特別像集合的交和並操作,而各個數相當於他們的因數的集合(可重複集)

lcm(a,b)=a*b/gcd(a,b) 就是一個兩個集合的容斥原理

然後類似的,推導 lcm(a_1,a_2,a_3,...,a_n) 和容斥原理類似的,有

lcm(a_1,a_2,...,a_n)=a_1*...*a_n / (gcd(a_1,a_2)*...) * (gcd(a_1,a_2,a_3)*...)... 這樣的

但是直接按這個寫法時間複雜度在指數級,需要改進(之後沒有用到這個上面這一小段其實,除了集合的思想

還是集合的想法,不如從集合各個元素著手,就像 lcm(6,8)=lcm(2^3,3^1)=2^3*3^1=24

即可以將一個大的集合分解成互不干擾的小集合,他們的lcm就是他們的乘積

而對同一個素因數的倍數來說,直接取最大的就行了,那麼將這個結論放到題目的情況中呢?

我們希望有斐波那契數有一個類似因子的存在,並且他們互不干擾,就稱他們為g_i好了,滿足 fib(a)=g_{x_1}*g_{x_2}*...*g_{a} ,其中xi為a的因子,這是絕對構造得出來的,證明如下

假設一直到n都滿足條件,對於n+1,有

fib(n+1)=g_{x_1}*...*g_{n+1} ,

g_(n+1)是還沒確定的,只需 g_{n+1}=fib(n+1)/(g_{x_1}*g_{x_2}*...) 這樣構造即可。(可以儲存g_xi的逆,因為需要用到多次

這樣我們就將fib的各個數變成了g元素的集合,求最終的lcm只要求g元素的並集即可,寫出來就是

lcm(fib(a_1),fib(a_2),...,fib(a_n))

=g_{x_1}*g_{x_2}*...*g_{x_m} (其中x1到xm為a_1,a_2,...,a_n的因子集合

大致估算時間複雜度應該是

O(求因子集合+求g)

=O(n*logn+max(a_i))

update:多謝評論區張同學提醒,我在推的時候太跳了,疏忽了一些,改成現在這樣應該也過得去吧?(如果還錯了x_x望再指正一下


這個數據範圍,暴力就行了。

-------------------------------------------------------

您弄錯數據範圍讓我很為難啊……

現在的數據範圍,用zyz的做法就行啦。

-----------------------------------------------------------------

我是 @阮行止 ,匿名是為了防止污染關注者timeline。


1355 斐波那契的最小公倍數 - ZLH_HHHH的博客 - CSDN博客


推薦閱讀:

如何判斷一條線段和一個矩形或者圓相交?
對大整數N開平方,求其整數部分,有什麼好的演算法嗎?
有沒有一種加密演算法可以識別不同密鑰加密的同一明文?
有什麼理論複雜但是實現簡單的演算法?
如何更好的理解和掌握 KMP 演算法?

TAG:演算法 | 編程 | C | OI |