DestinHistoire

 

BZOJ-2301 [HAOI2011]Problem b(莫比乌斯反演+容斥)

题目描述

  计算:

\[\sum\limits_{x=a}^{b}\sum\limits_{y=c}^{d}[\gcd(x,y)=k] \]

  数据范围:\(1\leq T,k,a,b,c,d\leq 5\times 10^4\)

分析

  设 \(f(a,b)=\displaystyle\sum_{i=1}^{a}\sum_{j=1}^{b}[\gcd(i,j)=k]\)

  则:

\[\begin{aligned}&f(a,b)\\ =&\sum_{i=1}^{a}\sum_{j=1}^{b}[\gcd(i,j)=k]\\ =&\sum_{i=1}^{\frac{a}{k}}\sum_{j=1}^{\frac{b}{k}}[\gcd(i,j)=1]\\ =&\sum_{i=1}^{\frac{a}{k}}\sum_{j=1}^{\frac{b}{k}}\sum_{d\mid \gcd(i,j)}\mu(d)\\ =&\sum_{i=1}^{\frac{a}{k}}\sum_{j=1}^{\frac{b}{k}}\sum_{d=1}^{\frac{a}{k}}\mu(d)·[d\mid \gcd(i,j)]\\ =&\sum_{d=1}^{\frac{a}{k}}\mu(d)\sum_{i=1}^{\frac{a}{k}}\sum_{j=1}^{\frac{b}{k}}[d\mid \gcd(i,j)]\\ =&\sum_{d=1}^{\frac{a}{k}}\mu(d)\Big\lfloor\frac{a}{kd}\Big\rfloor\Big\lfloor\frac{b}{kd}\Big\rfloor \end{aligned} \]

  答案为:

\[\sum\limits_{x=a}^{b}\sum\limits_{y=c}^{d}[\gcd(x,y)=k]\\ =\sum\limits_{x=1}^{b}\sum\limits_{y=1}^{d}[\gcd(x,y)=k]-\sum\limits_{x=1}^{b}\sum\limits_{y=1}^{c-1}[\gcd(x,y)=k]-\sum\limits_{x=1}^{a-1}\sum\limits_{y=1}^{d}[\gcd(x,y)=k]+\sum\limits_{x=1}^{a-1}\sum\limits_{y=1}^{c-1}[\gcd(x,y)=k]\\ =f(b,d)-f(b,c-1)-f(a-1,d)+f(a-1,c-1) \]

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
bool vis[N+10];
long long cnt,prime[N+10],mu[N+10],sum[N+10];
void init()
{
    mu[1]=1;
    for(int i=2;i<=N;i++)
    {
        if(!vis[i])
        {
            prime[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=N;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
                break;
            else
                mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=N;i++)
        sum[i]=sum[i-1]+mu[i];
}
long long solve(long long b,long long d,long long k)
{
    b=b/k,d=d/k;
    long long ans=0,n=min(b,d);
    for(int l=1,r;l<=n;l=r+1)
    {
        r=min(b/(b/l),d/(d/l));
        ans=ans+(sum[r]-sum[l-1])*(b/l)*(d/l);
    }
    return ans;
}
int main()
{
    init();
    int T;
    cin>>T;
    while(T--)
    {
        long long a,b,c,d,k;
        scanf("%lld %lld %lld %lld %lld",&a,&b,&c,&d,&k);
        printf("%lld\n",solve(b,d,k)-solve(b,c-1,k)-solve(a-1,d,k)+solve(a-1,c-1,k));
    }
    return 0;
}

posted on 2020-11-21 15:23  DestinHistoire  阅读(50)  评论(0)    收藏  举报

导航