zoukankan      html  css  js  c++  java
  • 斐波那契的最小公倍数 题解

    题目传送门

    题目大意

    给出 (n) 以及一个长度为 (n) 的数组 (a_{1,2,...,n}) ,定义 (f_i) 表示斐波拉契数列的第 (i) 项,其中 (f_1=f_2=1) 。求出 ( ext{lcm}{f_{a_1},f_{a_2},...,f_{a_n}})

    (nle 5 imes 10^4,a_ile 10^6)

    思路

    算是让我见识了 ( ext{min-max}) 容斥有多强。做这道题首先你得知道一个知道一个式子:

    [ ext{lcm}{S}=prod_{Tsubseteq S}gcd{T}^{(-1)^{|T|+1}} ]

    具体证明可以考虑我们对于质因数分解的每一位做 ( ext{min-max}) 容斥。

    然后看到这道题,我们又有一个人尽皆知的定理 (gcd(f_i,f_j)=f_{gcd(i,j)}),然后就可得到:

    [ ext{lcm}{S}=prod_{Tsubseteq S}f_{gcd{T}}^{(-1)^{|T|+1}} ]

    [=prod_{i=1}^{infty} f_i^{sum_{Tsubseteq S} [gcd{T}=i](-1)^{|T|+1}} ]

    然后上面那一坨不是很好求,所以我们可以考虑莫比乌斯反演解决,我们设 (a_i=sum_{Tsubseteq S} [gcd{T}=i](-1)^{|T|+1})(b_i=sum_{i|d} a_d),那么我们可以得到:

    [b_i=sum_{Tsubseteq S}[i|gcd{T}](-1)^{|T|+1} ]

    然后你发现如果 (i)(T) 中出现过,那么 (b_i=1),反之为 (0),具体证明可以使用二项式定理。

    然后我们使用莫比乌斯反演可以得到:

    [a_i=sum_{i|d}mu(frac{d}{i})b_d ]

    然后直接预处理之后暴力算就好了,时间复杂度为 (Theta(wln w)) ,其中 (w) 是值域。

    ( exttt{Code})

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define mod 1000000007
    #define MAX 1000000
    
    int n,tot,f[MAX + 5],a[MAX + 5],b[MAX + 5],mu[MAX + 5],vis[MAX + 5],prime[MAX + 5];
    
    void Euler (int up){
    	mu[1] = 1;
    	for (Int i = 2;i <= up;++ i){
    		if (!vis[i]) prime[++ tot] = i,mu[i] = -1;
    		for (Int j = 1;j <= tot && i * prime[j] <= up;++ j){
    			vis[i * prime[j]] = 1;
    			if (i % prime[j] == 0) break;
    			else mu[i * prime[j]] = -mu[i];
    		}
    	}
    }
    
    int qkpow (int a,int b){
    	int res = 1;for (;b;b >>= 1,a = 1ll * a * a % mod) if (b & 1) res = 1ll * res * a % mod;
    	return res;
    }
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    signed main(){
    	read (n),Euler (MAX);
    	for (Int i = 1,x;i <= n;++ i) read (x),b[x] = 1;
    	for (Int i = 1;i <= MAX;++ i)
    		for (Int j = i + i;j <= MAX;j += i)
    			b[i] |= b[j];
    	f[1] = f[2] = 1;for (Int i = 2;i <= MAX;++ i) f[i] = (f[i - 1] + f[i - 2]) % mod;
    	for (Int i = 1;i <= MAX;++ i)
    		for (Int j = i;j <= MAX;j += i)
    			a[i] += mu[j / i] * b[j];
    	int ans = 1;for (Int i = 1;i <= MAX;++ i) ans = 1ll * ans * qkpow (f[i],mod - 1 + a[i]) % mod;
    	write (ans),putchar ('
    ');
     	return 0;
    }
    
  • 相关阅读:
    docker 方式安装gitlab时,项目的clone地址及项目文件列表地址为机器名的问题解决办法
    CPU流水线
    Element中el-form嵌套el-table双击编辑提交检验
    java基础知识
    C#多线程下载
    mysql优化
    C++ 算法(一)
    前端vue 的面试总结 以及答案以及前端技术点面试
    C# 组合任务
    C# List去重DistinctBy扩展
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13556689.html
Copyright © 2011-2022 走看看