P2522 [HAOI2011]Problem b

传送门

对于每次询问 $a,b,c,d,n$ 答案就是 $f[n]=\sum_{i=a}^{b}\sum_{j=c}^{d}[gcd(i,j)==n]$

看到熟悉的 $gcd$ ,莫比乌斯反演

设 $F[n]=\sum_{i=a}^{b}\sum_{j=c}^{d}[n|gcd(i,j)]$,那么 $F[n]=\sum_{n|d}f[d]$

并且易知 $F[n]=(\left \lfloor \frac{b}{n} \right \rfloor-\left \lfloor \frac{a-1}{n} \right \rfloor) (\left \lfloor \frac{d}{n} \right \rfloor-\left \lfloor \frac{c-1}{n} \right \rfloor)$

直接反演:$f[n]=\sum_{n|d} \mu (d/n) F[d]=\sum_{n|d} \mu (d/n) (\left \lfloor \frac{b}{n} \right \rfloor-\left \lfloor \frac{a-1}{n} \right \rfloor) (\left \lfloor \frac{d}{n} \right \rfloor-\left \lfloor \frac{c-1}{n} \right \rfloor)$

枚举 $n$ 的倍数 $k$:变成 $f[n]=\sum_{k} \mu (k) (\left \lfloor \frac{b}{kn} \right \rfloor-\left \lfloor \frac{a-1}{kn} \right \rfloor) (\left \lfloor \frac{d}{kn} \right \rfloor-\left \lfloor \frac{c-1}{kn} \right \rfloor)$

因为 $\left \lfloor \frac{a-1}{kx} \right \rfloor=\left \lfloor \frac{\left \lfloor \frac{a-1}{x} \right \rfloor}{k} \right \rfloor$

所以 $f[n]=\sum_{k} \mu (k) (\left \lfloor \frac{ \left \lfloor \frac{b}{n} \right \rfloor }{k} \right \rfloor-\left \lfloor \frac{\left \lfloor \frac{a}{n} \right \rfloor}{k} \right \rfloor) (\left \lfloor \frac{\left \lfloor \frac{d}{n} \right \rfloor}{k} \right \rfloor-\left \lfloor \frac{\left \lfloor \frac{c}{n} \right \rfloor}{k} \right \rfloor)$

然后就可以数论分块了

总复杂度 $O( n \sqrt(n) )$

注意代码中的 $k$ 就是指前面的 $n$

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=2e6+7,M=5e4;
int Q,a,b,c,d,k,pri[N],mu[N],tot;
ll ans;
bool not_pri[N];
void pre()
{
    mu[1]=1;
    for(int i=2;i<=M;i++)
    {
        if(!not_pri[i]) pri[++tot]=i,mu[i]=-1;
        for(int j=1;j<=tot;j++)
        {
            ll t=1ll*i*pri[j]; if(t>M) break;
            not_pri[t]=1; if(!(i%pri[j])) break;
            mu[t]=-mu[i];
        }
    }
    for(int i=2;i<=M;i++) mu[i]+=mu[i-1];
}
int main()
{
    pre(); Q=read();
    while(Q--)
    {
        a=read(),b=read(),c=read(),d=read(),k=read();
        ans=0; a--,c--;/*注意a--,c--之后a,c可能为0*/ a/=k,b/=k,c/=k,d/=k;
        int mi=min(b,d);
        for(int l=1,r;l<=mi;l=r+1)
        {
            r=min( b/(b/l) , d/(d/l) );
            if(a/l) r=min(r,a/(a/l)); if(c/l) r=min(r,c/(c/l));//注意特判a,c等于0的情况
            ans+=1ll*(mu[r]-mu[l-1])*(b/l-a/l)*(d/l-c/l);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2019-07-04 21:48  LLTYYC  阅读(129)  评论(0编辑  收藏  举报