[联合集训6-26] 盒子 莫比乌斯反演+杜教筛

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DOFYPXY/article/details/80820488

题目就是求i=1nj=1ni+jgcd(i,j)2n2
枚举d=gcd(i,j)

d=1ni=1nj=1n[gcd(i,j)=d]i+jd

莫比乌斯反演,
k=1nμ(k)d=1nki=1nkdi=1nkdikd+jkdd=k=1nμ(k)kd=1nknkd2(nkd+1)

f(n)=i=1nμ(k)k,g(n)=i=1nni2(ni+1)。我们只要能筛f,g的就能分块求了。g显然能直接分块O(n)求,f可以卷上id函数之后用杜教筛求,具体地:
f(n)=i=1nd|iμ(d)didi=2nd|i,d<iμ(d)did

f(n)=1i=2nif(ni)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define up(x,y) (x=(x+(y))%mod)
using namespace std;
const int mod=1000000007,R=10000000;
int n,mk[R+5],pri[670000],num;
bool flag[R+5];
ll ans;
struct ha
{
    int cnt,con[R+5],a[R+5],b[R+5],nxt[R+5];
    void add(int x,int y)
    {
        int id=x%R;
        a[++cnt]=x;b[cnt]=y;
        nxt[cnt]=con[id];
        con[id]=cnt;
    }
    int qry(int x)
    {
        int id=x%R;
        for(int p=con[id];p;p=nxt[p])
            if(a[p]==x) return b[p];
        return -1;  
    }
}H;
void getpri(int n)
{
    memset(flag,1,sizeof(flag));
    flag[1]=0;mk[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(flag[i]) {pri[++num]=i;mk[i]=-i;}
        for(int j=1;j<=num&&i*pri[j]<=n;j++)
        {
            flag[i*pri[j]]=0;
            if(i%pri[j]==0) {mk[i*pri[j]]=0;break;}
            mk[i*pri[j]]=-mk[i]*pri[j];
        }
    }
    for(int i=2;i<=n;i++)
        up(mk[i],mk[i-1]);
}
ll djs(int n)
{
    if(n<=R) return mk[n];
    int hh=H.qry(n);
    if(hh!=-1) return hh;
    ll re=1;
    for(int l=2,r,x;l<=n;l=r+1)
        x=n/l,r=n/x,up(re,-djs(x)*((ll)(l+r)*(r-l+1)/2)%mod);
    H.add(n,re);
    return re; 
}
ll calc(int n)
{
    ll re=0;
    for(int l=1,r,x;l<=n;l=r+1)
        x=n/l,r=n/x,up(re,(ll)x*x%mod*(x+1)%mod*(r-l+1));
    return re;
}
ll solve(int n)
{
    ll re=0;
    for(int l=1,r,x;l<=n;l=r+1)
        x=n/l,r=n/x,up(re,(djs(r)-djs(l-1))*calc(x));
    return re;  
}
int main()
{
    freopen("box.in","r",stdin);
    freopen("box.out","w",stdout);
    scanf("%d",&n);
    getpri(R);  
    printf("%lld",((solve(n)-2ll*n*n)%mod+mod)%mod);        
    return 0;
}
展开阅读全文

没有更多推荐了,返回首页