51nod 1355 斐波那契的最小公倍数

Description

斐波那契数列定义如下:
\[
f[n]=
\begin{cases}
1 , & \text {if $n$ is equal to $0$ or $1$} \f(n-1) + f(n-2), & \text{otherwise}
\end{cases}
\]

给出 \(n\) 个正整数 \(a_1, a_2,\cdots ,a_n\) ,求对应的斐波那契数的最小公倍数,由于数字很大,输出 \(\bmod{ 1000000007}\) 的结果即可。

\(2\le N \le 50000,1 \le a_i\le 1000000\)

Solution

首先对于集合 \({S}\) 有
\[
lcm(S)=\prod_{T\subseteq S,T\ne\emptyset} \gcd(T) ^{(-1)^{|T|+1}}
\]
对于斐波那契数列有
\[
f(\gcd(a,b)) = \gcd(f(a), f(b))
\]
于是有
\[
\begin{align}
lcm(f_S)
&=\prod_{T\subseteq S,T\ne\emptyset} \gcd(f_T)^{(-1)^{|T|+1}} \&=\prod_{T\subseteq S,T\ne\emptyset} f_{\gcd(T)}^{(-1)^{|T|+1}}
\end{align}
\]

定义数列 \(g\)

\[
f_n=\sum_{d|n}g_d
\]

于是有
\[
\begin{align}
lcm(f_S)
&=\prod_{T\subseteq S,T\ne\emptyset} \gcd(f_T)^{(-1)^{|T|+1}} \&=\prod_{T\subseteq S,T\ne\emptyset} f_{\gcd(T)}^{(-1)^{|T|+1}} \&=\prod_{T\subseteq S,T\ne\emptyset} (\prod_{d|\gcd(T)}g_d)^{(-1)^{|T|+1}} \&=\prod_d g_d^{\sum_{T\subseteq S,T\ne \emptyset,d|\gcd(T)} (-1)^{|T|+1}}
\end{align}
\]
另有
\[
\sum_{T\subseteq S,T\ne \emptyset,d|\gcd(T)} (-1)^{|T|+1} =
\begin{cases}
1, & \exists x \in S,d|x\0, & \text{otherwise}
\end{cases}
\]
于是
\[
\begin{align}
lcm(f_S)
&=\prod_{T\subseteq S,T\ne\emptyset} \gcd(f_T)^{(-1)^{|T|+1}} \&=\prod_{T\subseteq S,T\ne\emptyset} f_{\gcd(T)}^{(-1)^{|T|+1}} \&=\prod_{T\subseteq S,T\ne\emptyset} (\prod_{d|\gcd(T)}g_d)^{(-1)^{|T|+1}} \&=\prod_d g_d^{\sum_{T\subseteq S,T\ne \emptyset,d|\gcd(T)} (-1)^{|T|+1}} \&=\prod_{\exists x \in S,d|x} g_d
\end{align}
\]
然后就可以直接算了。

另外对于 \(g\)
\[
g_n=f_n\times(\prod _{d|n,d\ne 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;
}

原文地址:https://www.cnblogs.com/aziint/p/9780437.html

时间: 2024-10-08 05:34:25

51nod 1355 斐波那契的最小公倍数的相关文章

1355 斐波那契的最小公倍数

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1355 斐波那契数列定义如下: F(0) = 0 F(1) = 1F(n) = F(n-1) + F(n-2) 给出n个正整数a1, a2,...... an,求对应的斐波那契数的最小公倍数,由于数字很大,输出Mod 1000000007的结果即可. 例如:1 3 6 9, 对应的斐波那契数为:1 2 8 34, 他们的最小公倍数为136. Input 第1行:1个数N,

51Nod - 1242 斐波那契数列的第N项

斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...) 给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可. Input输入1个数n(1 <= n <= 10^18).Output输出F(n) % 1000000009的结果.Sample Input 11 Sam

51nod 1242 斐波那契数列的第N项(矩阵快速幂)

1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...) 给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可. Input 输入1个数n(1 <=

51nod 1350 斐波那契表示 (找规律递推)

分析: - -! 找规律...首先可以归纳证明,对于n,最佳的取法是先取不大于n的最大的那个斐波那契数,然后递推.从而可以得到算出F(n)的一个方法,但是n的范围太大了,先算出n较小的情况,会发现: 第三列为F(n),第二列为G(n),可以看出第k块是由k-1块和k-2块+1合在一起得到的,从而可以先预处理前k块之和(k不会超过100),然后对于每个n,先找到最大的不超过n的那块,然后对剩下的项递归,总的复杂度为O(T*logn). 1 #include<iostream> 2 #includ

(矩阵快速幂)51NOD 1242斐波那契数列的第N项

斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...) 给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可. 输入 输入1个数n(1 <= n <= 10^18). 输出 输出F(n) % 1000000009的结果. 输入样例 11 输出样例 89解:由于斐波那

POJ 3070 + 51Nod 1242 大斐波那契数取余

POJ 3070 #include "iostream" #include "cstdio" using namespace std; class matrix { public: int a[2][2]; matrix() { a[0][0]=a[1][0]=a[0][1]=1; a[1][1]=0; } }; matrix multi(matrix a,matrix b) { matrix temp; int i,j,k; for(i=0;i<2;i++)

51Nod——T 1242 斐波那契数列的第N项

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1242 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...) 给出n,求F(n)

51nod Bash游戏(V1,V2,V3,V4(斐波那契博弈))

Bash游戏V1 有一堆石子共有N个.A B两个人轮流拿,A先拿.每次最少拿1颗,最多拿K颗,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N和K,问最后谁能赢得比赛. 例如N = 3,K = 2.无论A如何拿,B都可以拿到最后1颗石子. Input 第1行:一个数T,表示后面用作输入测试的数的数量.(1 <= T <= 10000) 第2 - T + 1行:每行2个数N,K.中间用空格分隔.(1 <= N,K <= 10^9) Output 共T

51NOD 1070 Bash游戏 V4(斐波那契博弈)

传送门 有一堆石子共有N个.A B两个人轮流拿,A先拿.每次拿的数量最少1个,最多不超过对手上一次拿的数量的2倍(A第1次拿时要求不能全拿走).拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N,问最后谁能赢得比赛. 例如N = 3.A只能拿1颗或2颗,所以B可以拿到最后1颗石子. Input 第1行:一个数T,表示后面用作输入测试的数的数量.(1 <= T <= 1000) 第2 - T + 1行:每行1个数N.(1 <= N <= 10^9) O