zoukankan      html  css  js  c++  java
  • [BZOJ 2301][HAOI2011]Problem b(莫比乌斯反演)

    Description

    对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

    Solution

    还是要学习一个

    莫比乌斯反演…

    进行优化,对mu维护一个前缀和

    学习资料的话推荐PoPoQQQ的ppt,还有莫比乌斯反演(宋新波)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define MAXN 50005
    #define Min(a,b) (a<b?a:b)
    using namespace std;
    typedef long long LL;
    int n,a,b,c,d,k;
    int mu[MAXN],sum[MAXN],pri[MAXN],cnt=0;
    bool jud[MAXN];
    void getmu()
    {
        mu[1]=1;
        for(int i=2;i<=MAXN;i++)
        {
            if(!jud[i])pri[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&pri[j]*i<=MAXN;j++)
            {
                jud[pri[j]*i]=1;
                if(i%pri[j]==0){mu[pri[j]*i]=0;break;}
                mu[pri[j]*i]=-mu[i];
            }
        }
        for(int i=1;i<=MAXN;i++)
        sum[i]=sum[i-1]+mu[i];
    }
    LL clac(int m,int n,int k)
    {
        LL res=0;int last;
        m/=k,n/=k;
        for(int i=1;i<=Min(n,m);i=last+1)
        {
            last=min(n/(n/i),m/(m/i));
            res+=(LL)(n/i)*(m/i)*(sum[last]-sum[i-1]);
        }
        return res;
    }
    int main()
    {
        scanf("%d",&n);getmu();
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
            printf("%lld
    ",clac(b,d,k)-clac(a-1,d,k)-clac(b,c-1,k)+clac(a-1,c-1,k));
        }
        return 0;
    }
  • 相关阅读:
    7月18日实习日志
    第二周总结
    7月15日实习日志
    7月14日实习日志
    7月13日实习日志
    7月12日实习日志
    7月11日实习日志
    第一周总结
    7月8日实习日志
    小飞机工作笔记(一)方案简述
  • 原文地址:https://www.cnblogs.com/Zars19/p/6685039.html
Copyright © 2011-2022 走看看