zoukankan      html  css  js  c++  java
  • [BZOJ]2301: [HAOI2011]Problem b

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

    思路:

    我们只要能求出1<=x<=n,1<=y<=m时的数对个数,容斥一下即可,求法如下:

    复制黄学长复制的鏼爷的题解

    推导:




    用莫比乌斯函数的性质把求和的式子换掉,

    其中,更换求和指标,

    容易知道单调不上升,且最多有种不同的取值。所以按取值分成个段分别处理,一个连续段内的和可以用预处理出的莫比乌斯函数前缀和求出

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 50000
    int u[MN+5],f[MN+5],p[MN+5],pn;
    int cal(int n,int m)
    {
        if(n>m)swap(n,m);
        int res=0,ls,i;
        for(i=1;i<=n;i=ls+1)
        {
            ls=min(n/(n/i),m/(m/i));
            res+=(u[ls]-u[i-1])*(n/i)*(m/i);
        }
        return res;
    }
    int main()
    {
        int n=read(),i,j,a,b,c,d,k;
        for(u[1]=1,i=2;i<=MN;++i)
        {
            if(!f[i])p[++pn]=i,u[i]=-1;
            for(j=1;i*p[j]<=MN&&(f[i*p[j]]=1);++j)
                if(i%p[j])u[i*p[j]]=-u[i];else break;
            u[i]+=u[i-1];
        }
        while(n--)a=read()-1,b=read(),c=read()-1,d=read(),k=read(),
            printf("%d
    ",cal(b/k,d/k)-cal(a/k,d/k)-cal(b/k,c/k)+cal(a/k,c/k));
    }
  • 相关阅读:
    Pandas | 21 日期功能
    Pandas | 20 级联
    Pandas | 19 合并/连接
    Pandas | GroupBy 分组
    Pandas | 缺失数据处理
    Pandas | 16 聚合
    Pandas | 15 窗口函数
    Pandas | 14 统计函数
    Pandas | 13 索引和选择数据
    Pandas | 12 选项和自定义
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ2301.html
Copyright © 2011-2022 走看看