zoukankan      html  css  js  c++  java
  • 51Nod.1237.最大公约数之和 V3(莫比乌斯反演 杜教筛 欧拉函数)

    题目链接

    (Description)

      (nleq 10^{10}),求

    [sum_{i=1}^nsum_{j=1}^ngcd(i,j) mod (1e9+7) ]

    (Solution)

      首先

    [sum_{i=1}^nsum_{j=1}^ngcd(i,j)=sum_{d=1}^ndsum_{i=1}^nsum_{j=1}^n[gcd(i,j)=d] ]

      注意不是(sum_{i=1}^nsum_{j=1}^ngcd(i,j)=sum_{d=1}^nsum_{i=1}^nsum_{j=1}^n[gcd(i,j)=d])

    [ egin{aligned} sum_{i=1}^nsum_{j=1}^ngcd(i,j)&=sum_{d=1}^ndsum_{i=1}^nsum_{j=1}^n[gcd(i,j)=d]\ &=sum_{d=1}^ndsum_{i=1}^{lfloorfrac{n}{d} floor}sum_{j=1}^{lfloorfrac{n}{d} floor}[gcd(i,j)=1]\ &=sum_{d=1}^ndsum_{i=1}^{lfloorfrac{n}{d} floor}mu(i)lfloorfrac{lfloorfrac{n}{d} floor}{i} floorlfloorfrac{lfloorfrac{n}{d} floor}{i} floor\ &=sum_{d=1}^ndsum_{d|t,tleq n}mu(frac{t}{d})(lfloorfrac{n}{t} floor)^2\ &=sum_{t=1}^n(lfloorfrac{n}{t} floor)^2sum_{d|t}dmu(frac{t}{d})\ &=sum_{t=1}^n(lfloorfrac{n}{t} floor)^2varphi(t) end{aligned} ]

      然后就可以杜教筛了。
      最后一步用到$$sum_{d|n}frac{n}{d}mu(d)=varphi(n)$$

    证明:
      首先有 (sum_{d|n}varphi(d)=n)(不证了).
      设 (f(n)=n),则(f(n)=sum_{d|n}varphi(d)).
      那么 (varphi(n)=sum_{d|n}f(frac{n}{d})mu(d))
      即 (sum_{d|n}frac{n}{d}mu(d)=varphi(n)).

    //前缀和不要忘取模。。
    #include<cstdio>
    #include<cstring>
    typedef long long LL;
    const int N=4500000,mod=1e9+7;
    
    int P[N>>2],cnt,phi[N+3];
    LL n,sum[N+3],sum2[100000];
    bool Not_P[N+3];
    
    void Init()
    {
    	phi[1]=1;
    	for(int i=2;i<=N;++i)
    	{
    		if(!Not_P[i]) P[++cnt]=i,phi[i]=i-1;
    		for(int j=1;j<=cnt&&i*P[j]<=N;++j)
    		{
    			Not_P[i*P[j]]=1;
    			if(i%P[j]) phi[i*P[j]]=phi[i]*(P[j]-1);
    			else {phi[i*P[j]]=phi[i]*P[j]; break;}
    		}
    	}
    	for(int i=1;i<=N;++i) sum[i]=sum[i-1]+phi[i], sum[i]>=mod?sum[i]-=mod:0;
    }
    LL FP(LL x,LL k)
    {
    	LL t=1;
    	for(;k;k>>=1,x=x*x%mod)
    		if(k&1) t=t*x%mod;
    	return t;
    }
    const LL inv2=FP(2,mod-2);
    LL Calc(LL x)
    {
    	if(x<=N) return sum[x];
    	else if(~sum2[n/x]) return sum2[n/x];
    	LL t=x%mod, res=t*(t+1)%mod*inv2%mod;
    	for(LL i=2,las;i<=x;i=las+1)
    		las=x/(x/i),(res-=(las-i+1)*Calc(x/i)%mod)%=mod;
    	return sum2[n/x]=(res+mod)%mod;
    }
    
    int main()
    {
    	Init();//scanf("%I64d",&n);
    	scanf("%lld",&n);
    	memset(sum2,0xff,sizeof sum2);
    	LL res=0;
    	for(LL i=1,las,t;i<=n;i=las+1)
    		las=n/(n/i), t=n/i%mod, (res+=t*t%mod*(Calc(las)-Calc(i-1)+mod)%mod)%=mod;
    	printf("%lld",res);
    
    	return 0;
    }//9800581876
    
  • 相关阅读:
    C# 调用Java Webservice 加入SoapHeader 验证信息
    SqlServer查找表中多余的重复记录
    INI文件的读写
    Sql触发器脚本
    Sql遍历更新脚本
    CAS 单点登录,通过ticket 获取登录用户
    模块 | 验证格式
    aja如何解决跨域请求?
    说说各个浏览器box模型
    Vue 双向数据绑定原理分析
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8412639.html
Copyright © 2011-2022 走看看