###题解:
这题肯定是我做过的最简单的八级算法题了。
设 F i Fi Fi为斐波拉契序列的第i项。
通过打表可得:
g
c
d
(
F
n
,
F
m
)
=
F
g
c
d
(
n
,
m
)
gcd(Fn,Fm)=F_{gcd(n,m)}
gcd(Fn,Fm)=Fgcd(n,m)
接下来尝试去证明这个结论。
首先斐波拉契序列有一个递推式:
F
n
+
m
=
F
n
−
1
∗
F
m
+
F
n
∗
F
m
+
1
F_{n+m}=F_{n-1}*F_{m}+F_{n}*F_{m+1}
Fn+m=Fn−1∗Fm+Fn∗Fm+1
还有一个结论就是 g c d ( F n − 1 , F n ) = 1 gcd(F_{n-1},F_n)=1 gcd(Fn−1,Fn)=1。
这两个结论都是显然的,就不证明了。
不妨设
n
<
m
n<m
n<m,那么
g
c
d
(
F
n
,
F
m
)
gcd(Fn,Fm)
gcd(Fn,Fm)
=
g
c
d
(
F
n
,
F
n
−
1
∗
F
m
−
n
+
F
n
∗
F
m
−
n
+
1
)
=gcd(F_n,F_{n-1}*F_{m-n}+F_n*F_{m-n+1})
=gcd(Fn,Fn−1∗Fm−n+Fn∗Fm−n+1)
因为
F
n
∗
F
m
−
n
+
1
F_n*F_{m-n+1}
Fn∗Fm−n+1一定是
F
n
F_n
Fn的倍数,因此可以直接去掉。
=
g
c
d
(
F
n
,
F
n
−
1
∗
F
m
−
n
)
=gcd(F_n,F_{n-1}*F_{m-n})
=gcd(Fn,Fn−1∗Fm−n)
因为
g
c
d
(
F
n
,
F
n
−
1
)
=
1
gcd(F_n,F_{n-1})=1
gcd(Fn,Fn−1)=1,所以可以去掉
=
g
c
d
(
F
n
,
F
m
−
n
)
=gcd(F_n,F_{m-n})
=gcd(Fn,Fm−n)
。
发现下标在更相减损,归纳可得
g
c
d
(
F
n
,
F
m
)
=
F
g
c
d
(
n
,
m
)
gcd(Fn,Fm)=F_{gcd(n,m)}
gcd(Fn,Fm)=Fgcd(n,m)
l c m lcm lcm有一个容斥求法:
l
c
m
(
a
1
,
a
2
,
…
,
a
n
)
lcm(a1,a2,…,an)
lcm(a1,a2,…,an)
=
∏
b
∈
a
且
b
≠
∅
g
c
d
(
b
1
,
b
2
,
…
,
b
∣
b
∣
)
−
1
∣
b
∣
+
1
=\prod_{b∈a且b≠∅}~gcd(b1,b2,…,b_{|b|})^{-1^{|b|+1}}
=∏b∈a且b̸=∅ gcd(b1,b2,…,b∣b∣)−1∣b∣+1
证明可通过对每一个质因子单独讨论得到。
设 q i q_i qi为 a i a_i ai含质因子p的幂次。
原式等价于:
=
∏
b
∈
q
且
b
≠
∅
m
i
n
(
b
i
)
−
1
∣
b
∣
+
1
=\prod_{b∈q且b≠∅}~min(b_i)^{-1^{|b|+1}}
=∏b∈q且b̸=∅ min(bi)−1∣b∣+1
假设已经把q从小到大排序了
=
∑
k
=
1
n
q
k
∗
∑
i
=
0
n
−
k
C
n
−
k
i
∗
(
−
1
)
i
=\sum_{k=1}^n q_k *\sum_{i=0}^{n-k}C_{n-k}^i*(-1)^{i}
=∑k=1nqk∗∑i=0n−kCn−ki∗(−1)i
=
∑
k
=
1
n
q
k
∗
[
n
−
k
=
0
]
=\sum_{k=1}^n q_k*[n-k=0]
=∑k=1nqk∗[n−k=0]
=
q
n
=q_n
=qn
=
排
序
前
的
m
a
x
(
q
)
=排序前的max(q)
=排序前的max(q)
把每个质因子合并起来即得证。
设 f i f_i fi表示 g c d gcd gcd恰好为 i i i的每种方案×这种方案的容斥系数(就是那个-1的多少次方)的和。
直接算不好算,于是反演一下, g i g_i gi定义类似,为 g c d gcd gcd是 i i i的倍数的XXX
设读入的n个数中有k个数是i的倍数,则 g ( k ) = [ k > 0 ] g(k)=[k>0] g(k)=[k>0]
由
g
i
=
∑
i
∣
j
f
j
g_i=\sum_{i|j}f_j
gi=∑i∣jfj得
f
i
=
∑
i
∣
j
g
j
∗
μ
(
j
/
i
)
f_i=\sum_{i|j}g_j*\mu(j/i)
fi=∑i∣jgj∗μ(j/i)
至此此题完成,写起来真的好写,就是证明有点多。
Code:
#include<cstdio>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int mo = 1e9 + 7;
const int N = 1e6;
int n, x;
bool bz[N + 1];
int p[N], mu[N + 1], s[N + 1], f[N + 1];
ll ksm(ll x, ll y) {
if(y < 0) x = ksm(x, mo - 2), y = -y;
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
int main() {
f[0] = 0; f[1] = 1; mu[1] = 1;
fo(i, 2, N) {
f[i] = (f[i - 1] + f[i - 2]) % mo;
if(!bz[i]) p[++ p[0]] = i, mu[i] = -1;
for(int j = 1; i * p[j] <= N; j ++) {
int k = i * p[j]; bz[k] = 1;
if(i % p[j] == 0) {mu[k] = 0; break;}
mu[k] = -mu[i];
}
}
scanf("%d", &n);
fo(i, 1, n) scanf("%d", &x), s[x] ++;
fo(i, 1, N) {
fo(j, 2, N / i) s[i] += s[i * j];
s[i] = s[i] > 0;
}
fo(i, 1, N) fo(j, 2, N / i) s[i] += s[i * j] * mu[j];
ll ans = 1; fo(i, 1, N) ans = ans * ksm(f[i], s[i]) % mo;
printf("%lld", ans);
}