zoukankan      html  css  js  c++  java
  • 【[国家集训队]Crash的数字表格 / JZPTAB】

    这道题我们要求的是

    [sum_{i=1}^Nsum_{j=1}^Mlcm(i,j) ]

    总所周知(lcm)的性质不如(gcd)优雅,但是唯一分解定理告诉我们(gcd(i,j) imes lcm(i,j)=i imes j)

    所以很容易的可以转化成这个柿子

    [sum_{i=1}^Nsum_{j=1}^Mfrac{i imes j}{(i,j)} ]

    现在开始套路了

    先设两个函数

    [f(n)=sum_{i=1}^Nsum_{j=1}^M[(i,j)==n] imes i imes j ]

    [F(n)=sum_{i=1}^Nsum_{j=1}^M[n|(i,j)] imes i imes j ]

    [=frac{n imes(left lfloor frac{N}{n} ight floor+1) imes left lfloor frac{N}{n} ight floor}{2} imesfrac{n imes(left lfloor frac{M}{n} ight floor+1) imes left lfloor frac{M}{n} ight floor}{2} ]

    显然则有

    [F(n)=sum_{n|d}f(d) ]

    反演得

    [f(n)=sum_{n|d}mu(frac{d}{n})F(d) ]

    于是答案就是

    [Ans=sum_{i=1}^Nfrac{f(i)}{i} ]

    [=sum_{i=1}^N imesfrac{1}{i}sum_{i|d}mu(frac{d}{i})frac{d imes(left lfloor frac{N}{d} ight floor+1) imes left lfloor frac{N}{d} ight floor}{2} imesfrac{d imes(left lfloor frac{M}{d} ight floor+1) imes left lfloor frac{M}{d} ight floor}{2} ]

    后面的一大坨东西真是太烦人了,搞到前面来

    [Ans=sum_{d=1}^Nfrac{(left lfloor frac{N}{d} ight floor+1) imes left lfloor frac{N}{d} ight floor imes(left lfloor frac{M}{d} ight floor+1) imes left lfloor frac{M}{d} ight floor}{4}sum_{i|d}frac{mu(frac{d}{i}) imes d^2}{i} ]

    于是我们可以用(Theta(n ln n))来求出(sum_{i|d}frac{mu(frac{d}{i}) imes d^2}{i})之后前缀和

    于是有了一个(70)分的代码

    
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 10000005
    #define LL long long
    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    const LL mod=20101009;
    int n,m;
    int f[maxn],p[maxn>>2];
    LL pre[maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        if(n>m) std::swap(n,m);
        f[1]=pre[1]=1;
        for(re int i=2;i<=n;i++)
        {
            if(!f[i]) p[++p[0]]=i,pre[i]=(1-i+mod);
            for(re int j=1;j<=p[0]&&p[j]*i<=n;j++)
            {
                f[p[j]*i]=1;
                if(i%p[j]==0) 
                {
                    pre[i*p[j]]=pre[i];
                    break;
                }
                pre[p[j]*i]=pre[p[j]]*pre[i]%mod;
            }
        }
        for(re int i=1;i<=n;i++) pre[i]=(i*pre[i]%mod+pre[i-1])%mod;
        LL ans=0;
        for(re LL l=1,r;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            LL N=n/l,M=m/l;
            ans=(ans+((N+1)*N/2%mod)*((M+1)*M/2%mod)%mod*(pre[r]-pre[l-1]+mod)%mod)%mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
    

    显然不行

    我们设(T=frac{d}{i})

    那么

    [sum_{i|d}frac{mu(frac{d}{i}) imes d^2}{i}=d imessum_{T|d}mu(T) imes T ]

    定义(h(x)=sum_{T|x}mu(T) imes T)

    会发现(h)是一个积性函数,可以考虑如何线筛

    首先(x)是质数(h(x)=1-x)

    互质的话可以直接乘起来

    如果不互质的话需要好好考虑一下了

    仔细思考一下这个(h)的含义,会发现有一些约数(T)是没有用的,就是那些(mu(T)=0)的约数

    而线筛的时候一旦(i\%p[j]==0),说明(p[j])(i)中出现过,于是(p[j])并不能组成一些新的有用约数,函数值和(h(i))相比其实没有什么变化,所以就有

    [h(p[j]*i)=h(i) ]

    于是现在的答案变成了

    [Ans=sum_{d=1}^Nfrac{(left lfloor frac{N}{d} ight floor+1) imes left lfloor frac{N}{d} ight floor imes(left lfloor frac{M}{d} ight floor+1) imes left lfloor frac{M}{d} ight floor}{4} imes d imes h(d) ]

    于是直接求(d imes h(d))的前缀和就好了

    代码

    
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 10000005
    #define LL long long
    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    const LL mod=20101009;
    int n,m;
    int f[maxn],p[maxn>>2];
    LL pre[maxn];
    int main()
    {
    	scanf("%d%d",&n,&m);
    	if(n>m) std::swap(n,m);
    	f[1]=pre[1]=1;
    	for(re int i=2;i<=n;i++)
    	{
    		if(!f[i]) p[++p[0]]=i,pre[i]=(1-i+mod);
    		for(re int j=1;j<=p[0]&&p[j]*i<=n;j++)
    		{
    			f[p[j]*i]=1;
    			if(i%p[j]==0) 
    			{
    				pre[i*p[j]]=pre[i];
    				break;
    			}
    			pre[p[j]*i]=pre[p[j]]*pre[i];
    		}
    	}
    	for(re int i=1;i<=n;i++) pre[i]=(i*pre[i]%mod+pre[i-1])%mod;
    	LL ans=0;
    	for(re LL l=1,r;l<=n;l=r+1)
    	{
    		r=min(n/(n/l),m/(m/l));
    		LL N=n/l,M=m/l;
    		ans=(ans+((N+1)*N/2%mod)*((M+1)*M/2%mod)%mod*(pre[r]-pre[l-1]+mod)%mod)%mod;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    动态Webapi参考资料
    解决异步事务好文章
    .net core 插件开发
    端口被占用代码
    性能测试
    .NET/.NET Core 单元测试:Specflow
    Autofac 替换默认控制器骚操作
    Swagger非常好的文章
    sqlserver入门到精通(2016安装教程)
    springboot 学习之路 27(实现ip白名单功能)
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205675.html
Copyright © 2011-2022 走看看