【51nod 2026】Gcd and Lcm

题目

已知 \(f(x)=\sum_{d|x}μ(d)∗d\)
现在请求出下面式子的值
\(\sum_{i=1}^{n}\sum_{j=1}^{n}f(gcd(i,j))∗f(lcm(i,j))\)
由于值可能过大所以请对 10^9+7 取模
\(n≤10^9\)

分析

\(f\)为积性函数,
因为\(lcm(i,j)\)\(gcd(i,j)\)的任意一个质因子的指数和\(i\)\(j\)其中一个的相同。
对于每个质因子分开考虑, \(f(gcd(i,j))f(lcm(i,j))=f(i)f(j)\)
\[ans=\sum_{i=1}^{n}\sum_{j=1}^{n}f(i)f(j)\]
\[=(\sum_{i=1}^{n}f(i))^2\]
现在考虑如何求\(\sum_{i=1}^{n}f(i)\)
\[=\sum_{i=1}^{n}\sum_{d|i}μ(d)∗d\]
\[=\sum_{i=1}^{n}\sum_{d=1}^{\lfloor \frac{n}{i} \rfloor}μ(d)∗d\]
\[=\sum_{d=1}^{n}μ(d)∗d\lfloor \frac{n}{d} \rfloor\]
\(F(d)=μ(d)∗d,S(n)=\sum_{i=1}^{n}F(i)\)
发现\(F*id=e\)(因为\(\sum_{d|n}μ(d)∗d*\lfloor \dfrac{n}{d} \rfloor\)=[n=1])
于是
\[1=\sum_{i=1}^{n}\sum_{d|i}μ(d)∗d*\lfloor \dfrac{i}{d} \rfloor\]
\(T=\lfloor \dfrac{i}{d} \rfloor\)
\[=\sum_{T=1}^{n}T\sum_{d|T}μ(d)∗d\]
\[=\sum_{T=1}^{n}T\sum_{d=1}^{\lfloor \frac{n}{T} \rfloor}μ(d)∗d\]
\[=\sum_{T=1}^{n}TS(\lfloor \frac{n}{T} \rfloor)\]
于是
\[S(n)=1-\sum_{T=2}^{n}TS(\lfloor \frac{n}{T} \rfloor)\]
杜教筛一下.
\(ans=S(n)^2\)

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
const int maxlongint=2147483647;
const long long mo=1e9+7;
const int lim=1e5+7;
const int N=10000005;
using namespace std;
#define sqr(x) (1ll*(x)*(x)%mo)
#define val(x,y) (1ll*(y-x+1)*(x+y)/2%mo)
int p[N],mu[N],n,ha[lim+5][2],s[N],ans;
bool bz[N];
int get(int v)
{
    int x;
    for(x=v%lim;ha[x][0] && ha[x][0]!=v;(++x)-=x>=lim?lim:0);
    return x;
}
int S(int m)
{
    if(m<=N-5) return s[m];
    int pos=get(m);
    if(ha[pos][0]) return ha[pos][1];
    ha[pos][0]=m;
    int la=0,sum=0;
    for(int i=2;i<=m;i=la+1)
    {
        la=m/(m/i);
        sum=(1ll*sum+1ll*val(i,la)*S(m/i))%mo;
    }
    return ha[pos][1]=(1-sum+mo)%mo;
}
int main()
{
    freopen("2026.in","r",stdin);
    //freopen("2026.out","w",stdout);
    scanf("%d",&n);
    mu[1]=s[1]=1;
    for(int i=2;i<=N-5;i++)
    {
        if(!bz[i]) mu[p[++p[0]]=i]=-1;
        s[i]=(s[i-1]+mu[i]*i+mo)%mo;
        for(int j=1,k;j<=p[0] && (k=i*p[j])<=N-5;j++)
        {
            bz[k]=true;
            if(i%p[j]==0) break;
            mu[k]=-mu[i];
        }
    }
    int la=1;
    for(int i=1;i<=n;i=la+1)
    {
        la=n/(n/i);
        ans=(1ll*ans+1ll*(S(la)-S(i-1)+mo)*(n/i))%mo;
    }
    printf("%lld",sqr(ans));
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9079721.html
今日推荐