传送门
题解:
首先所有相同的数只保留一个。
然后由于 g c d gcd gcd和 l c m lcm lcm可以表示成各个质因子的次数取 max \max max和 min \min min的情况,我们由 M i n − M a x Min-Max Min−Max容斥可以得到:
l c m ( S ) = ∏ T ⊂ S g c d ( T ) − 1 ∣ T ∣ + 1 lcm(S)=\prod_{T\sub S}gcd(T)^{-1^{|T|+1}} lcm(S)=T⊂S∏gcd(T)−1∣T∣+1
注意上面的式子那里有双重指数。
斐波那契数有一个性质: g c d ( f n , f m ) = f g c d ( n , m ) gcd(f_n,f_m)=f_{gcd(n,m)} gcd(fn,fm)=fgcd(n,m)
这里给出一个证明,由于 f n = f n − 1 + f n − 2 f_n=f_{n-1}+f_{n-2} fn=fn−1+fn−2,归纳可知: g c d ( f n , f n − 1 ) = 1 gcd(f_n,f_{n-1})=1 gcd(fn,fn−1)=1,同时有一个递推的性质: 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+1∗fn+fm∗fn−1,由以上两个结论可以方便地推出上面那个性质。
g c d ( f n + m , f n ) = g c d ( f n − 1 ⋅ f m + f n ⋅ f m + 1 , f n ) = g c d ( f m , f n ) gcd(f_{n+m},f_n)=gcd(f_{n-1}\cdot f_m+f_n\cdot f_{m+1},f_n)=gcd(f_m,f_n) gcd(fn+m,fn)=gcd(fn−1⋅fm+fn⋅fm+1,fn)=gcd(fm,fn)
下标上的迭代会在到达 g c d ( n , m ) gcd(n,m) gcd(n,m)时候停止。归纳可以知道 g c d ( f n , f m ) = f g c d ( n , m ) gcd(f_n,f_m)=f_{gcd(n,m)} gcd(fn,fm)=fgcd(n,m)
对我们要求的东西进行转化:
A n s = l c m ( f S ) = ∏ T ⊂ S g c d ( f T ) − 1 ∣ T ∣ + 1 = ∏ T ⊂ S f g c d ( T ) − 1 ∣ T ∣ + 1 \begin{aligned} Ans&=&&lcm(f_S)\\ &=&&\prod_{T\sub S}gcd(f_T)^{-1^{|T|+1}}\\ &=&&\prod_{T\sub S}f_{gcd(T)}^{-1^{|T|+1}} \end{aligned} Ans===lcm(fS)T⊂S∏gcd(fT)−1∣T∣+1T⊂S∏fgcd(T)−1∣T∣+1
感觉这个玩意不好算,观察到数据范围只有 1 e 6 1e6 1e6,所以我们感觉可以上 O ( A log A ) O(A\log A) O(AlogA)的反演来一下。
考虑构造函数 g n g_n gn满足: f n = ∏ d ∣ n g d f_n=\prod_{d\mid n}g_d fn=∏d∣ngd
于是可以继续化简: A n s = ∏ T ⊂ S ∏ d ∣ g c d ( T ) g d − 1 ∣ T ∣ + 1 = ∏ d g d ∑ T ⊂ S [ d ∣ g c d ( T ) ] ( − 1 ∣ T ∣ + 1 ) \begin{aligned} Ans&=&&\prod_{T\sub S}\prod_{d\mid gcd(T)}g_d^{-1^{|T|+1}}\\ &=&&\prod_{d}g_d^{\sum_{T\sub S}[d\mid gcd(T)](-1^{|T|+1})} \end{aligned} Ans==T⊂S∏d∣gcd(T)∏gd−1∣T∣+1d∏gd∑T⊂S[d∣gcd(T)](−1∣T∣+1)
我们观察一下上面这个式子中的指数: ∑ T ⊂ S [ d ∣ g c d ( T ) ] ( − 1 ∣ T ∣ + 1 ) \sum_{T\sub S}[d\mid gcd(T)](-1^{|T|+1}) T⊂S∑[d∣gcd(T)](−1∣T∣+1)
看上去不好处理,但是由这种集合的性质(或许应该称为 g c d gcd gcd的性质,但是总得来说还是来自容斥)我们知道:
∑ T ⊂ S [ d ∣ g c d ( T ) ] ( − 1 ∣ T ∣ + 1 ) = { 1 ∃ a ∈ S , [ d ∣ a ] 0 o t h e r w i s e \sum_{T\sub S}[d\mid gcd(T)](-1^{|T|+1})=\left\{ \begin{aligned} 1 &&& \exist a\in S ,[d\mid a]\\ 0 &&&otherwise \end{aligned} \right. T⊂S∑[d∣gcd(T)](−1∣T∣+1)={10∃a∈S,[d∣a]otherwise
于是我们可以 O ( n log n ) O(n\log n) O(nlogn)处理 g g g数组,然后随便做了。
但是实际上我们没必要算出 g g g数组,我们直接算出在所有 g g g的乘积中, f i f_i fi出现了多少次就行了。
这个也可以在调和级数时间内算出来。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
cs int N=1e6+6;
int lim;
int f[N],cnt[N];
int n,ans=1;
bool a[N];
signed main(){
// freopen("fiblcm.in","r",stdin);
scanf("%d",&n);
for(int re i=1;i<=n;++i){
int x;scanf("%d",&x);
a[x]=true;
lim=std::max(lim,x);
}
f[1]=1;for(int re i=2;i<=lim;++i)f[i]=add(f[i-1],f[i-2]);
for(int re i=lim;i>2;--i){
for(int re j=i;j<=lim&&!a[i];j+=i)a[i]|=a[j];
if(!a[i])continue;
cnt[i]=1;
for(int re j=i+i;j<=lim;j+=i)cnt[i]-=cnt[j];
int tmp=cnt[i]%(mod-1);
if(tmp<0)tmp+=mod-1;
if(tmp)ans=mul(ans,power(f[i],tmp));
}
cout<<ans<<"\n";
return 0;
}