zoukankan      html  css  js  c++  java
  • BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演

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

        然后对于求这样单个的gcd(x,y)=k的,我们通常采用莫比乌斯反演

    但是,时间复杂度是O(n*(n/k))的,当复杂度很坏的时候,当k=1时,退化到O(n^2),超时

    然后进行分块优化,时间复杂度是O(n*sqrt(n))

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int N=5e4+5;
    const int INF=0x3f3f3f3f;
    bool vis[N];
    int prime[N],mu[N],cnt;
    void getmu()
    {
        mu[1] = 1;
        for(int i=2; i<=N-5; i++)
        {
            if(!vis[i])
            {
                prime[++cnt] = i;
                mu[i] = -1;
            }
            for(int j=1; j<=cnt&&i*prime[j]<=N-5; j++)
            {
                vis[i*prime[j]] = 1;
                if(i%prime[j]) mu[i*prime[j]] = -mu[i];
                else
                {
                    mu[i*prime[j]] = 0;
                    break;
                }
            }
        }
    }
    LL solve(int n,int m,int k){
       n/=k,m/=k;
       int l=min(n,m);
       LL ans=0;
       for(int i=1,j;i<=l;i=j+1){
         j=min(n/(n/i),m/(m/i));
         ans+=1ll*(mu[j]-mu[i-1])*(n/i)*(m/i);
       }
       return ans;
    }
    int main(){
        getmu();
        for(int i=1;i<=N-5;++i)mu[i]+=mu[i-1];
        int T;
        scanf("%d",&T);
        while(T--){
           int a,b,c,d,k;
           scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
           printf("%lld
    ",solve(b,d,k)-solve(b,c-1,k)-solve(a-1,d,k)+solve(a-1,c-1,k));
        }   
        return 0;
    }
    View Code
  • 相关阅读:
    linux查看与设置主机名
    为什么用户主目录下.bash_profile没有自动执行
    sqlplus查看服务名
    linux之cp/scp命令+scp命令详解
    查看磁盘使用量
    yum源
    微软输入法删除
    Android下 ionic view 无法登录
    inline-block在ie6中的经典bug
    Apache端口配置
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5440507.html
Copyright © 2011-2022 走看看