【51nod1355】斐波那契的最小公倍数(min - max容斥)(容斥)(反演)

题意:
m m m 个数 a i a_i ai,求 l c m ( f i b ( a i ) ) lcm(fib(a_i)) lcm(fib(ai)) m ≤ 4 e 5 , a i ≤ 1 e 6 m\le 4e5, a_i\le 1e6 m4e5,ai1e6,对 1 e 9 + 7 1e9+7 1e9+7 取模


首先我们知道斐波那契数列的一些性质

  1. g c d ( f i b i , f i b i − 1 ) = 1 gcd(fib_i,fib_{i-1})=1 gcd(fibi,fibi1)=1
  2. f n + m = f m + 1 ∗ f n + f m ∗ f n − 1 f_{n+m}=f_{m+1}*f_n+f_m*f_{n-1} fn+m=fm+1fn+fmfn1
  3. g c d ( f n + m , f n ) = g c d ( f m + 1 ∗ f n + f m ∗ f n − 1 , f n ) = g c d ( f m , f n ) ⇒ g c d ( f n , f m ) = f g c d ( n , m ) gcd(f_{n+m},f_n)=gcd(f_{m+1}*f_n+f_m*f_{n-1},f_n)=gcd(f_m,f_n)\Rightarrow gcd(f_n,f_m)=f_{gcd(n,m)} gcd(fn+m,fn)=gcd(fm+1fn+fmfn1,fn)=gcd(fm,fn)gcd(fn,fm)=fgcd(n,m)

第 2 个可以用归纳法证明,不是很难

我们考虑把求 l c m lcm lcm 变成 g c d gcd gcd m i n   m a x min\ max min max 容斥
m i m_i mi 表示质因子次数, S S S m i m_i mi 的集合

l c m ( f i b ( a i ) ) = ∏ p i m a x ( S ) = ∏ p i ∑ T ⊂ S ( − 1 ) ∣ T ∣ + 1 m i n ( T ) lcm(fib(a_i))=\prod p_i^{max(S)}=\prod p_i^{\sum_{T\subset S}(-1)^{|T|+1}min(T)} lcm(fib(ai))=pimax(S)=piTS(1)T+1min(T)
= ∏ T ⊂ S ∏ i p i ( − 1 ) ∣ T ∣ + 1 ∗ m i n ( T ) =\prod_{T\subset S} \prod_ip_i^{(-1)^{|T|+1}*min(T)} =TSipi(1)T+1min(T)
= ∏ T ⊂ S g c d ( T ) ( − 1 ) ∣ T ∣ + 1 =\prod_{T\subset S}gcd(T)^{(-1)^{|T|+1}} =TSgcd(T)(1)T+1

发现不是很好搞,考虑反演,令 f ( n ) = ∏ T ⊂ S , g c d ( T ) = n f i b ( n ) ( − 1 ) ∣ T ∣ + 1 , g ( n ) = ∏ n ∣ d f ( d ) f(n)=\prod_{T\subset S,gcd(T)=n}fib(n)^{(-1)^{|T|+1}},g(n)=\prod_{n|d}f(d) f(n)=TS,gcd(T)=nfib(n)(1)T+1,g(n)=ndf(d)

那么有 g ( n ) = ∏ T ⊂ S , g c d ( T ) ∣ n f i b ( n ) ( − 1 ) ∣ T ∣ + 1 g(n)=\prod_{T\subset S,gcd(T)|n}fib(n)^{(-1)^{|T|+1}} g(n)=TS,gcd(T)nfib(n)(1)T+1
不妨另为 g c d gcd gcd 倍数且在 S S S 的集合为 A A A,那么

g ( n ) = ∏ T ⊂ A f i b ( n ) ( − 1 ) ∣ T ∣ + 1 = f i b ( n ) ( A ≠ ∅ ) g(n)=\prod_{T\subset A}fib(n)^{(-1)^{|T|+1}}=fib(n)(A\ne\empty) g(n)=TAfib(n)(1)T+1=fib(n)(A=)

f ( n ) = g ( n ) ∗ ( ∏ n ∣ d , d ! = n f ( d ) ) − 1 f(n)=g(n)*(\prod_{n|d,d!=n} f(d))^{-1} f(n)=g(n)(nd,d!=nf(d))1

倒过来调和级数求即可

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 1e6 + 5;
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int ksm(int a, int b){ int ans=1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans=mul(ans,a); return ans; }
int n, a[N], g[N], f[N], mx;
int main(){
	cin >> n;
	for(int i = 1, x; i <= n; i++){
		scanf("%d", &x); a[x] = 1;
		mx = max(mx, x);
	}
	f[1] = 1;
	for(int i = 2; i <= mx; i++) f[i] = add(f[i-1], f[i-2]);
	for(int i = mx; i >= 1; i--) 
	for(int j = i+i; j <= mx; j += i) a[i] |= a[j];
	for(int i = 1; i <= mx; i++) g[i] = f[i];
	for(int i = 1; i <= mx; i++){
		int iv = ksm(g[i], Mod-2);
		for(int j = i+i; j <= mx; j += i) g[j] = mul(g[j], iv);
	}
	int ans = 1; 
	for(int i = 1; i <= mx; i++) if(a[i]) ans = mul(ans, g[i]);
	cout << ans; return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值