zoukankan      html  css  js  c++  java
  • 51nod 1227 平均最小公倍数【欧拉函数+杜教筛】

    以后这种题能用phi的就不要用mu…mu往往会带着个ln然后被卡常致死
    把题目要求转换为前缀和相减的形式,写出来大概是要求这样一个式子:

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

    注意j的限制是i

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

    [sum_{d=1}^{n}sum_{i=1}^{left lfloor frac{n}{d} ight floor}sum_{j=1}^{i}[gcd(i,j)==1]frac{jd}{d} ]

    [sum_{d=1}^{n}sum_{i=1}^{left lfloor frac{n}{d} ight floor}sum_{j=1}^{i}[gcd(i,j)==1]j ]

    然后有一个打表找规律发现的式子:

    [sum_{i=1}^{n}sum_{j=1}^{i}[gcd(i,j)==1]i*j=sum_{i=1}^{n}i*frac{phi(i)*i+[i==1]}{2} ]

    于是原式可转化为:

    [sum_{d=1}^{n}sum_{i=1}^{left lfloor frac{n}{d} ight floor}frac{phi(i)*i+[i==1]}{2} ]

    [frac{sum_{d=1}^{n}sum_{i=1}^{left lfloor frac{n}{d} ight floor}phi(i)*i}{2}+frac{n}{2} ]

    先不考虑后面的加和下面的除二,于是要求的就是:

    [sum_{d=1}^{n}sum_{i=1}^{left lfloor frac{n}{d} ight floor}phi(i)*i ]

    ( sum_{i=1}^{left lfloor frac{n}{d} ight floor}phi(i)*i )的部分显然可以用杜教筛处理,然后拒绝算时间复杂度。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const long long N=1000005,m=1000000,inv6=166666668,inv2=500000004,mod=1e9+7;
    long long a,b,n,phi[N],q[N],tot,ha[N];
    bool v[N];
    long long clc1(long long x)
    {
    	return x*(x+1)%mod*inv2%mod;
    }
    long long clc2(long long x)
    {
    	return x*(x+1)%mod*(2*x+1)%mod*inv6%mod;
    }
    long long slv(long long x)
    {
    	if(x<=m)
    		return phi[x];
    	if(ha[n/x])
    		return ha[n/x];
    	long long re=clc2(x);
    	for(long long i=2,la;i<=x;i=la+1)
    	{
    		la=x/(x/i);
    		re=(re-(clc1(la)-clc1(i-1))%mod*slv(x/i)%mod)%mod;
    	}
    	return ha[n/x]=re;
    }
    long long wk(long long x)
    {
    	n=x;
    	memset(ha,0,sizeof(ha));
    	long long re=0ll;
    	for(long long i=1,la;i<=x;i=la+1)
    	{
    		la=x/(x/i);
    		re=(re+(la-i+1)*slv(x/i)%mod)%mod;
    	}
    	return (re+x)*inv2%mod;
    }
    int main()
    {
    	phi[1]=1;
    	for(long long i=2;i<=m;i++)
    	{
    		if(!v[i])
    		{
    			q[++tot]=i;
    			phi[i]=i-1;
    		}
    		for(long long j=1;j<=tot&&i*q[j]<=m;j++)
    		{
    			long long k=i*q[j];
    			v[k]=1;
    			if(i%q[j]==0)
    			{
    				phi[k]=phi[i]*q[j];
    				break;
    			}
    			phi[k]=phi[i]*(q[j]-1);
    		}
    	}
    	for(long long i=1;i<=m;i++)
    		phi[i]=(phi[i-1]+phi[i]*i%mod)%mod;
    	scanf("%lld%lld",&a,&b);
    	printf("%lld
    ",((wk(b)-wk(a-1))%mod+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    Java基础知识强化之集合框架笔记20:数据结构之 栈 和 队列
    Java基础知识强化之集合框架笔记19:List集合迭代器使用之 并发修改异常的产生原因 以及 解决方案
    模块已加载,但对dllregisterServer的调用失败
    sql回滚
    BAT 批处理脚本 教程
    shell脚本小技巧
    shell if
    REDHAT4.8安装yum
    Linux中文显示乱码解决
    Nginx配置文件详细说明
  • 原文地址:https://www.cnblogs.com/lokiii/p/8327746.html
Copyright © 2011-2022 走看看