51nod 1355 斐波那契的最小公倍数
Posted aziint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1355 斐波那契的最小公倍数相关的知识,希望对你有一定的参考价值。
Description
斐波那契数列定义如下:
[
f[n]=
egin{cases}
1 , & ext {if $n$ is equal to $0$ or $1$} f(n-1) + f(n-2), & ext{otherwise}
end{cases}
]
给出 (n) 个正整数 (a_1, a_2,cdots ,a_n) ,求对应的斐波那契数的最小公倍数,由于数字很大,输出 (mod{ 1000000007}) 的结果即可。
(2le N le 50000,1 le a_ile 1000000)
Solution
首先对于集合 ({S}) 有
[
lcm(S)=prod_{Tsubseteq S,T
eemptyset} gcd(T) ^{(-1)^{|T|+1}}
]
对于斐波那契数列有
[
f(gcd(a,b)) = gcd(f(a), f(b))
]
于是有
[
egin{align}
lcm(f_S)
&=prod_{Tsubseteq S,T
eemptyset} gcd(f_T)^{(-1)^{|T|+1}} &=prod_{Tsubseteq S,T
eemptyset} f_{gcd(T)}^{(-1)^{|T|+1}}
end{align}
]
定义数列 (g)
[ f_n=sum_{d|n}g_d ]
于是有
[
egin{align}
lcm(f_S)
&=prod_{Tsubseteq S,T
eemptyset} gcd(f_T)^{(-1)^{|T|+1}} &=prod_{Tsubseteq S,T
eemptyset} f_{gcd(T)}^{(-1)^{|T|+1}} &=prod_{Tsubseteq S,T
eemptyset} (prod_{d|gcd(T)}g_d)^{(-1)^{|T|+1}} &=prod_d g_d^{sum_{Tsubseteq S,T
e emptyset,d|gcd(T)} (-1)^{|T|+1}}
end{align}
]
另有
[
sum_{Tsubseteq S,T
e emptyset,d|gcd(T)} (-1)^{|T|+1} =
egin{cases}
1, & exists x in S,d|x , & ext{otherwise}
end{cases}
]
于是
[
egin{align}
lcm(f_S)
&=prod_{Tsubseteq S,T
eemptyset} gcd(f_T)^{(-1)^{|T|+1}} &=prod_{Tsubseteq S,T
eemptyset} f_{gcd(T)}^{(-1)^{|T|+1}} &=prod_{Tsubseteq S,T
eemptyset} (prod_{d|gcd(T)}g_d)^{(-1)^{|T|+1}} &=prod_d g_d^{sum_{Tsubseteq S,T
e emptyset,d|gcd(T)} (-1)^{|T|+1}} &=prod_{exists x in S,d|x} g_d
end{align}
]
然后就可以直接算了。
另外对于 (g)
[
g_n=f_n imes(prod _{d|n,d
e n} g_d)^{-1}
]
#include<bits/stdc++.h>
using namespace std;
template <class T> void read(T &x) {
x = 0; bool flag = 0; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) flag |= ch == '-';
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48; flag ? x = 0 - x : 0;
}
#define N 10000010
#define rep(i, a, b) for (auto i = (a); i <= (b); ++i)
#define drp(i, a, b) for (auto i = (a); i >= (b); --i)
#define ll long long
#define P 1000000007
int n, a[N], f[N], g[N];
int qpow(int x, int k) {
int ret = 1;
for (; k; k >>= 1, x = 1ll * x * x % P) if (k & 1) ret = 1ll * ret * x % P;
return ret;
}
void init() {
f[1] = 1;
rep(i, 2, n) f[i] = (f[i - 2] + f[i - 1]) % P;
rep(i, 1, n) g[i] = f[i];
rep(i, 1, n) {
int inv = qpow(g[i], P - 2);
for (int j = i + i; j <= n; j += i) g[j] = 1ll * g[j] * inv % P;
}
}
bool vis[N];
int main() {
read(n); int _n = 0;
rep(i, 1, n) read(a[i]), _n = max(a[i], _n), vis[a[i]] = 1;
n = _n;
init();
int ans = 1;
rep(i, 1, n) {
bool tag = 0;
for (int j = i; j <= n; j += i) if (vis[j]) { tag = 1; break; }
if (tag) ans = 1ll * ans * g[i] % P;
}
printf("%d", ans);
return 0;
}
以上是关于51nod 1355 斐波那契的最小公倍数的主要内容,如果未能解决你的问题,请参考以下文章