zoukankan      html  css  js  c++  java
  • LOJ6102「2017 山东二轮集训 Day1」第三题 or 51nod1355 斐波那契的最小公倍数 题解

    Problem

    给出 (n) 个数 (a_1,a_2,dots,a_n) ,求出 (operatorname{lcm}(f(a_1),f(a_2,)dots,f(a_n)) mod 10^9+7) ,其中, (f(i)) 代表斐波那契数列第 (i) 项。

    Solution

    感觉挺妙的,记录一下。 以下 (S,T) 代表一类数的集合。

    我们知道斐波那契数列的一个性质:

    (gcdleft(f(i),f(j) ight)=fleft(gcd(i,j) ight))

    以及类比 (min-max) 容斥,我们可以有:

    (operatorname{lcm}(S) = prod_{Tsubseteq S,T eq varnothing}gcd(f(T))^{(-1)^{|T|+1}})

    然后就有一个非常妙的变换:

    类比莫比乌斯反演,构造数列 (g_1,g_2,dots,g_n) 满足 (f(n) = prod_{d|n}g(d)) ,移项后可得 (g(n) = f(n)prod_{d|n,d eq n}g(d)^{-1})

    然后:

    (egin{align} operatorname{lcm}(S) &= prod_{Tsubseteq S,T eq varnothing}gcdleft(f(T) ight)^{(-1)^{|T|+1}} \ &= prod_{Tsubseteq S,T eq varnothing}f(gcd(T))^{(-1)^{|T|+1}}\&=prod_{Tsubseteq S,T e varnothing}fleft(prod_{d|n}g(d) ight)^{(-1)^{|T|+1}}\ &= prod_{dge1}g(d)^{sum_{Tsubseteq S,T e varnothing,d|gcd(T)}(-1)^{|T|+1}}end{align})

    对于 (sum_{Tsubseteq S,T e varnothing,d|gcd(T)}(-1)^{|T|+1}) ,若存在 (d|x) , 则为 (1) ,否则为 (0)

    于是,

    (egin{align} operatorname{lcm}(S) &= prod_{dge1}g(d)^{sum_{Tsubseteq S,T e varnothing,d|gcd(T)}(-1)^{|T|+1}} \&= prod_{exists xin S,d|x,dge1}g(d)end{align})

    直接计算即可。

    Code

    #define in read()
    
    typedef long long ll;
    
    const int mod = 1e9+7;
    const int N = 50010;
    const int M = 1e6+10;
    
    ll f[M],g[M];
    int n,a[N],A;
    bool vis[M];
    
    ll qp(ll x,int t){ll res=1;for(;t;t>>=1,x=x*x%mod)if(t&1)res=res*x%mod;return res;}
    
    void getg(){
    	f[1] = 1;for(int i = 2;i <= A;i++) f[i] = (f[i-1] + f[i-2]) % mod;
    	for(int i = 1;i <= A;i++) g[i] = f[i];
    	for(int i = 1;i <= A;i++){
    		ll inv = qp(g[i],mod-2);
    		for(int j = i+i;j <= A;j += i) g[j] = g[j] * inv % mod;
    	}
    }
    
    int main (){
    	n = in; for(int i = 1;i <= n;i++) a[i] = in,A = max(a[i],A),vis[a[i]] = 1;
    	getg(); ll ans = 1;
    	for(int i = 1;i <= A;i++){
    		bool app = 0;
    		for(int j = i;j <= A;j+=i) if(vis[j]) {app = 1;break;}
    		if(app) ans = ans * g[i] % mod;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    本博客作者:Werner_Yin(https://www.cnblogs.com/werner-yin/) ,转载时请注明出处,谢谢支持!
  • 相关阅读:
    Excel中substitute替换函数的使用方法
    如何在Excel中提取小数点后面的数字?
    提升单元测试体验的利器--Mockito使用总结
    SpringMVC项目读取不到外部CSS文件的解决办法及总结
    java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
    Spring-data-redis操作redis知识总结
    优雅高效的MyBatis-Plus工具快速入门使用
    Thrift入门初探(2)--thrift基础知识详解
    Thrift入门初探--thrift安装及java入门实例
    spring事件驱动模型--观察者模式在spring中的应用
  • 原文地址:https://www.cnblogs.com/werner-yin/p/solution-LOJ-6102.html
Copyright © 2011-2022 走看看