P2522 [HAOI2011]Problem b

【题意】

 

 【分析】

首先我们可以简单容斥一下

设$calc(x,y)=\sum_{i=1}^{x}\sum_{j=1}^{y}[gcd(i,j)=1]$

那么$ans=calc(b,d)-calc(a-1,d)-calc(c-1,b)+calc(a-1,c-1)$

然后求$calc(x,y)$的套路就和P3455 [POI2007]ZAP-Queries一致了,就不再赘述了

【代码】

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
#define lson now<<1
#define rson now<<1|1
typedef long long ll;
const int maxn=5e4+5;
int n,a,b,c,d,x;
int np[maxn],cnt,mu[maxn],p[maxn];
int sum[maxn];
void init()
{
    mu[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!np[i])
        {
            mu[i]=-1;
            p[++cnt]=i;
        }
        for(int j=1;p[j]*i<maxn;j++)
        {
            np[i*p[j]]=1;
            if(i%p[j]==0)
            {
                mu[i*p[j]]=0;
                break;
            }
            else mu[i*p[j]]=-mu[i];
        }
    }
    for(int i=1;i<maxn;i++) sum[i]=sum[i-1]+mu[i];
}
ll calc(int x,int y,int k)
{
    ll res=0;
    x/=k; y/=k;
    for(int i=1,j;i<=min(x,y);i=j+1)
    {
        j=min(x/(x/i),y/(y/i));
        res+=1LL*(sum[j]-sum[i-1])*(x/i)*(y/i);
    }
    return res;
}
int main()
{
    // freopen("a.in","r",stdin);
    // freopen("a.out","w",stdout);
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&x);
        ll ans=0;
        ans=calc(b,d,x)-calc(a-1,d,x)-calc(b,c-1,x)+calc(a-1,c-1,x);
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2021-06-07 11:50  andyc_03  阅读(28)  评论(0编辑  收藏  举报