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;
    }
    
    
  • 相关阅读:
    线性代数思维导图——3.向量
    微分中值定理的基础题型总结
    构造函数
    Python课程笔记(七)
    0241. Different Ways to Add Parentheses (M)
    0014. Longest Common Prefix (E)
    0013. Roman to Integer (E)
    0011. Container With Most Water (M)
    0010. Regular Expression Matching (H)
    0012. Integer to Roman (M)
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205675.html
Copyright © 2011-2022 走看看