• 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\ 0, & 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;
    }
    
  • 相关阅读:
    C语言 exit 函数 C语言零基础入门教程
    C/C++ getchar函数 C语言零基础入门教程
    自己动手重新实现LINQ to Objects: 7 Count和LongCount
    自己动手重新实现LINQ to Objects: 5 Empty
    自己动手重新实现LINQ to Objects: 8 Concat
    自己动手重新实现LINQ to Objects: 11 First,Last,Single以及它们带有OrDefault的重载
    自己动手重新实现LINQ to Objects: 3 Select
    自己动手重新实现LINQ to Objects: 2 Where
    自己动手重新实现LINQ to Objects: 10 Any和All
    用豆瓣读书Chrome插件,简单购买电子书
  • 原文地址:https://www.cnblogs.com/aziint/p/9780437.html
Copyright © 2020-2023  润新知