zoukankan      html  css  js  c++  java
  • 51nod 1355斐波那契数列的最小公倍数

    woc好神

    不愧是8级题

    题意:

    给定 (n(nle 50000)) 个正整数 (a_i(1le a_ile 10^6))

    你需要计算:

    [ ext{lcm}(F(a_1),F(a_2)...F(a_n)) ]

    答案对(1e9+7)取模。

    其中(F(i))表示斐波那契数列第 (i) 项。

    ( m Sol:)

    我们应当注意到一个这样的基本事实:

    考虑到( m lcm)可以看作对于因数分解下的每一位取(max),而(gcd)则可以看作对因数分解下的每一位取(min)

    于是我们会发现在我们一无所知的情况下我们所求的( m lcm)(gcd)居然可以通过(min -max)容斥处理。

    具体来说是因为( m lcm)看作指数取(max)( m gcd)看作指数取(min)所以我们会发现其相当于对于指数做一个(min-max)容斥即可。

    然后我们发现每个因数的贡献是乘起来的,所以我们得到:

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

    这个式子丢到指数上一看就能明白正确性了(

    然后又因为对于斐波那契数列而言,存在:(gcd(f(a),f(b))=f(gcd(a,b)))

    于是我们所求为:

    [prod_{Tsub S}f(gcd(a...))^{(-1)^{|T|+1}} ]

    注意到值域并不大,我们考虑莫比乌斯反演,考虑化简原式应当为:

    [prod_{i=1}^{10^6} f(i)^{[gcd_{iin T}(a_i)==i](-1)^{(|T|+1)}} ]

    我们考虑统计上式,不妨令(F(x))表示(gcd) 至少是(x)的指数贡献和

    初步考虑后注意到对于(F(x)),假定有(k)(i)满足(x|a_i),则可知(F(x))为:

    [sum_{i=1}^{k}dbinom{k}{i}(-1)^{|i|+1} ]

    注意到这个式子的值恒定为:([k e 0])

    然后我们令(g(i))表示恰好

    则可得:

    [F(x)=sum_{x|d}g(d) ]

    [g(d)=sum_{d|x}mu(frac{x}{d})F(x) ]

    直接反演即可。

    注意到答案肯定很小,我们甚至不需要使用欧拉定理。

    然后这道题的斐波那契数列实际上是当作(f_1=1,f_2=1)这样推的= =,这一点破坏了这道题的和谐美感。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define rep( i, s, t ) for( register int i = s; i <= t; ++ i )
    #define re register
    #define int long long
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int M = 1e6 + 5 ;
    const int N = 1e5 + 5 ;
    const int P = 1e9 + 7 ;
    int n, m, a[N], mu[M], p[N], f[M], F[M], Ans, top ; 
    bool isp[M], cnt[M] ; 
    void init( int x ) {
    	f[2] = f[1] = 1, mu[1] = 1, isp[1] = 1 ;
    	for( re int i = 2; i <= x; ++ i ) {
    		if( i != 2 ) f[i] = ( f[i - 1] + f[i - 2] ) % P ;
    		if( !isp[i] ) p[++ top] = i, mu[i] = -1 ;
    		for( re int j = 1; j <= top && p[j] * i <= x; ++ j ) {
    			isp[p[j] * i] = 1 ;
    			if( i % p[j] == 0 ) break ;
    			mu[i * p[j]] = - mu[i] ;
    		}
    	}
    }
    int fpow( int x, int k ) {
    	int ans = 1, base = x ; 
    	while( k ) {
    		if( k & 1 ) ans = ans * base % P ;
    		base = base * base % P, k >>= 1 ; 
    	} return ans % P ; 
    }
    signed main()
    {
    	n = gi(), init(1e6), Ans = 1 ; 
    	rep( i, 1, n ) a[i] = gi(), cnt[a[i]] = 1, m = max( m, a[i] ) ;
    	for( re int i = 1; i <= m; ++ i )
    	for( re int j = i; j <= m; j += i ) cnt[i] |= cnt[j] ;
    	for( re int i = 1; i <= m; ++ i )
    	for( re int j = i; j <= m; j += i ) F[i] += mu[j / i] * cnt[j] ;
    	for( re int i = 1; i <= m; ++ i ) {
    		if( F[i] > 0 ) Ans = ( Ans * fpow( f[i], F[i] ) % P ) ;
    		if( F[i] < 0 ) Ans = ( Ans * fpow( fpow( f[i], -F[i] ), P - 2 ) ) % P ;
    	}
    	printf("%lld
    ", Ans ) ;
    	return 0 ;
    }
    
  • 相关阅读:
    图片懒加载
    浅谈javascript的函数节流
    js字符串常用方法详解
    js数组详解
    thinkphp3.2 批量添加数据
    openssl证书及配置
    手机访问PC端
    mui框架(三)
    mui框架(二)
    mui框架(一)
  • 原文地址:https://www.cnblogs.com/Soulist/p/12251483.html
Copyright © 2011-2022 走看看