• #min-max容斥#51nod 1355 斐波那契的最小公倍数


    题目

    对于 (nleq 50000,a_ileq 10^6),求 (large lcm(fib(a_1),fib(a_2),dots,fib(a_{n-1}),fib(a_n)))


    分析

    可以发现最小公倍数实际上是取所有质因子幂次的最大值,
    然而最大公约数更好求,考虑min-max容斥,也就是

    [large lcm(S)=prod_{Tsube S} gcd(T)^{(-1)^{|T|-1}} ]

    由于 (gcd(fib(a_1),fib(a_2),dots,fib(a_{n-1}),fib(a_n))=fib(gcd(a_1,a_2,dots,a_{n-1},a_n)))
    那么

    [large lcm(S)=prod_{T'sube S} fib(gcd(T'))^{(-1)^{|T'|-1}} ]

    考虑枚举最大公约数,也就是说所有数都要是其倍数,但是这样也很难处理,
    那么设 (fib(S)=prod_{Tsube S}g(T)),则

    [large g(S)=frac{fib(S)}{prod_{T subsetneqq S}g(T)} ]

    把原来的 (fib) 消掉就是

    [large lcm(S)=prod g(d)^{sum_{Tsube S,d|gcd(T)}{(-1)^{|T|-1}}} ]

    (n) 个数为 (d) 的倍数,那么指数就是

    [sum_{i=1}^n(-1)^{i-1}C(n,i)=1-sum_{i=0}^n(-1)^iC(n,i)=1-(1-1)^n=[n>0] ]

    那也就是

    [large lcm(S)=prod_{exist d|a_i} g(d) ]


    代码

    #include <cstdio>
    #include <cctype>
    using namespace std;
    const int N=1000011,mod=1000000007;
    int n,f[N],v[N],ans=1,mx;
    int iut(){
    	int ans=0; char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    int ksm(int x,int y){
    	int ans=1;
    	for (;y;y>>=1,x=1ll*x*x%mod)
    	    if (y&1) ans=1ll*ans*x%mod;
    	return ans;
    }
    int main(){
    	n=iut(),f[1]=1;
    	for (int i=1;i<=n;++i){
    		int x=iut(); v[x]=1;
    		mx=mx>x?mx:x;
    	}
    	for (int i=2;i<=mx;++i) f[i]=(f[i-1]+f[i-2])%mod;
    	for (int i=1;i<=mx;++i){
    		int now=ksm(f[i],mod-2);
    		for (int j=i+i;j<=mx;j+=i)
    		    f[j]=1ll*f[j]*now%mod;
    	}
    	for (int i=1;i<=mx;++i)
    	for (int j=i;j<=mx;j+=i) if (v[j])
    	    {ans=1ll*ans*f[i]%mod; break;}
    	return !printf("%d",ans);
    }
    
  • 相关阅读:
    PKU 1860 Currency Exchange 最短路 bellman
    PKU 3259 Wormholes 最短路 bellman
    bzoj3514
    bzoj2594
    bzoj3901
    bzoj2843&&1180
    bzoj2631
    bzoj2049
    bzoj2002
    bzoj1146
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15511829.html
Copyright © 2020-2023  润新知