[机房测试]太阳神

(2021.9.13)

Description

给定 (nleq 10^{10}),求

[sum_{i=1}^n sum_{j=1}^n Big[frac{ij}{(i,j)}> nBig] ]

Solution

补集转换,然后进一步化简。

[egin{align} &n^2-sum_{i=1}^n sum_{j=1}^n Big[frac{ij}{(i,j)} leq nBig] \ =&n^2-sum_{d=1}^n sum_{k=1}^{frac{n}{d}} mu(k) sum_{i=1}^{frac{n}{kd}} sum_{j=1}^{frac{n}{kd}} Big[ijk^2dleq nBig] end{align} ]

特别的点在于很多上界都是无效的,因为往大了取对答案没有影响。然后 (k) 比较特殊,带了一个 (mu) 的项,其他项都是类似的,只是上界不同。考虑把 (k^2) 除过去,那么 (k) 就可以枚举了,因为有 (k^2leq n)。然后更新一下上界,就可以得到

[sum_{k=1}^{sqrt{n}} mu(k) sum_{d=1}sum_{i=1}sum_{j=1} [ijdleq frac{n}{k^2}] ]

所以可以枚举 (k),然后计算三元组 ((i,j,d)) 的个数,令 (rg=frac{n}{k^2})。因为这三者完全对称,所以可以钦定一种大小关系然后乘上一个系数。例如,一种是 (a<b<c) ,就有 (6) 种可以将 (i,j,d) 代入的方式。考虑如何计算。因为 (a) 是最小的,所以有 (a^3leq rg),那么 (a) 就可以枚举了,再枚举一个 (b) 满足 (b^2leq frac{rg}{a}),然后 (d) 的范围就可以快速计算。剩下还有其中两个数相同和三个都相同的情况,不再赘述。复杂度 (O(能过))

#include<stdio.h>
#include<math.h>

typedef long long ll;

const int N=1e5+7;
const int Mod=1e9+7;

bool mk[N];
int mu[N],p[N],cnt=0;

ll calc(ll rg){
    ll ret=0;
    for(ll i=1;i*i*i<=rg;i++)
        for(ll j=i+1;j+1<=(rg/(i*j));j++)
            ret=(ret+6ll*(rg/(i*j)-j)%Mod)%Mod;
    for(ll i=1;i*i<=rg;i++)
        ret=(ret+3ll*((rg/(i*i))%Mod-(i<=(rg/(i*i)))))%Mod;
    for(ll i=1;i*i*i<=rg;i++) ret++;
    return ret%Mod;
}

int main(){
    freopen("ra.in","r",stdin);
    freopen("ra.out","w",stdout);
    ll n; scanf("%lld",&n);
    int rg=(int)(sqrt(n)+0.5); mu[1]=1;
    for(int i=2;i<=rg;i++){
        if(!mk[i]) p[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt&&p[j]*i<=rg;j++){
            mk[p[j]*i]=1;
            if(i%p[j]==0) break;
            mu[p[j]*i]=-mu[i];
        }
    }
    ll ans=0;
    for(ll d=1;d<=rg;d++)
        ans=(ans+mu[d]*calc(n/(d*d))+Mod)%Mod;
    printf("%lld",((n%Mod)*(n%Mod)-ans+Mod)%Mod);
}
原文地址:https://www.cnblogs.com/wwlwQWQ/p/15262533.html